home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 217 / DPCS0306DVD.ISO / Toolkit / Internet / FileZilla / Server / FileZilla_Server-0.9.11.exe / source / ControlSocket.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-11-12  |  77.6 KB  |  2,997 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // ControlSocket.cpp: Implementierungsdatei
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "ControlSocket.h"
  24. #include "transfersocket.h"
  25. #include "ServerThread.h"
  26. #include "Options.h"
  27. #include "Permissions.h"
  28. #include "AsyncGssSocketLayer.h"
  29. #include "AsyncSslSocketLayer.h"
  30. #include <math.h>
  31. #include "iputils.h"
  32.  
  33. #ifdef _DEBUG
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37.  
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CControlSocket
  40.  
  41. std::map<CStdString, int> CControlSocket::m_UserCount;
  42. CCriticalSectionWrapper CControlSocket::m_Sync;
  43.  
  44. CControlSocket::CControlSocket(CServerThread *pOwner)
  45. {
  46.     m_status.loggedon = FALSE;
  47.     m_status.hammerValue = 0;
  48.     m_transferstatus.socket = NULL;
  49.     m_transferstatus.ip = "";
  50.     m_transferstatus.port = -1;
  51.     m_transferstatus.pasv = -1;
  52.     m_transferstatus.rest = 0;
  53.     m_transferstatus.type = -1;
  54.     m_bWaitGoOffline = FALSE;
  55.     GetSystemTime(&m_LastTransferTime);
  56.     GetSystemTime(&m_LastCmdTime);
  57.     GetSystemTime(&m_LoginTime);
  58.     m_bQuitCommand = FALSE;
  59.  
  60.     ASSERT(pOwner);
  61.     m_pOwner = pOwner;
  62.  
  63.     m_nTelnetSkip = 0;
  64.     m_nRecvBufferPos = 0;
  65.  
  66.     m_pSendBuffer = NULL;
  67.     m_nSendBufferLen = 0;
  68.  
  69.     m_pGssLayer = NULL;
  70.     m_pSslLayer = NULL;
  71.  
  72.     for (int i = 0; i < 2; i++)
  73.     {
  74.         m_SlQuotas[i].bContinue = false;
  75.         m_SlQuotas[i].nBytesAllowedToTransfer = -1;
  76.         m_SlQuotas[i].nTransferred = 0;
  77.         m_SlQuotas[i].bBypassed = true;
  78.     }
  79.  
  80.     m_transferMode = mode_stream;
  81.  
  82.     m_zlibLevel = 8;
  83.  
  84.     m_antiHammeringWaitTime = 0;
  85.     m_bProtP = false;
  86. }
  87.  
  88. CControlSocket::~CControlSocket()
  89. {
  90.     if (m_status.loggedon)
  91.     {
  92.         DecUserCount(m_status.user);
  93.         m_pOwner->DecIpCount(m_status.ip);
  94.         m_status.loggedon=FALSE;
  95.     }
  96.     t_connop *op = new t_connop;
  97.     op->data = 0;
  98.     op->op = USERCONTROL_CONNOP_REMOVE;
  99.     op->userid = m_userid;
  100.     m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  101.     if (m_transferstatus.socket)
  102.         delete m_transferstatus.socket;
  103.     m_transferstatus.socket=0;
  104.  
  105.     delete [] m_pSendBuffer;
  106.     m_nSendBufferLen = 0;
  107.  
  108.     RemoveAllLayers();
  109.     delete m_pGssLayer;
  110.     delete m_pSslLayer;
  111. }
  112.  
  113. /////////////////////////////////////////////////////////////////////////////
  114. // Member-Funktion CControlSocket
  115.  
  116. #define BUFFERSIZE 500
  117. void CControlSocket::OnReceive(int nErrorCode)
  118. {
  119.     if (m_antiHammeringWaitTime)
  120.     {
  121.         if (nErrorCode)
  122.         {
  123.             //Control connection has been closed
  124.             Close();
  125.             SendStatus("disconnected.", 0);
  126.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  127.         }
  128.         return;
  129.     }
  130.  
  131.     int len = BUFFERSIZE;
  132.     int nLimit = GetSpeedLimit(upload);
  133.     if (!nLimit)
  134.     {
  135.         ParseCommand();
  136.         return;
  137.     }
  138.     if (len > nLimit && nLimit != -1)
  139.         len = nLimit;
  140.  
  141.     unsigned char *buffer = new unsigned char[BUFFERSIZE];
  142.     int numread = Receive(buffer, len);
  143.     if (numread != SOCKET_ERROR && numread)
  144.     {
  145.         if (nLimit != -1)
  146.             m_SlQuotas[upload].nTransferred += numread;
  147.  
  148.         m_pOwner->IncRecvCount(numread);
  149.         //Parse all received bytes
  150.         for (int i=0; i<numread; i++)
  151.         {
  152.             if (!m_nRecvBufferPos)
  153.             {
  154.                 //Remove telnet characters
  155.                 if (m_nTelnetSkip)
  156.                 {
  157.                     if (m_nTelnetSkip == 2)
  158.                     {
  159.                         if (buffer[i]<251 || buffer[i]>254)
  160.                             m_nTelnetSkip--;
  161.                     }
  162.                     m_nTelnetSkip--;
  163.                 }
  164.                 else if (buffer[i] == 255)
  165.                     m_nTelnetSkip = 2;
  166.  
  167.                 if (m_nTelnetSkip)
  168.                     continue;
  169.             }
  170.  
  171.             //Check for line endings
  172.             if ((buffer[i]=='\r')||(buffer[i]==0)||(buffer[i]=='\n'))
  173.             {
  174.                 //If input buffer is not empty...
  175.                 if (m_nRecvBufferPos)
  176.                 {
  177.                     m_RecvBuffer[m_nRecvBufferPos] = 0;
  178.                     m_RecvLineBuffer.push_back(m_RecvBuffer);
  179.                     m_nRecvBufferPos = 0;
  180.  
  181.                     //Signal that there is a new command waiting to be processed.
  182.                     GetSystemTime(&m_LastCmdTime);
  183.                 }
  184.             }
  185.             else
  186.                 //The command may only be 2000 chars long. This ensures that a malicious user can't
  187.                 //send extremely large commands to fill the memory of the server
  188.                 if (m_nRecvBufferPos < 2000)
  189.                     m_RecvBuffer[m_nRecvBufferPos++] = buffer[i];
  190.         }
  191.     }
  192.     else
  193.     {
  194.         if (!numread || GetLastError() != WSAEWOULDBLOCK)
  195.         {
  196.             //Control connection has been closed
  197.             Close();
  198.             SendStatus("disconnected.", 0);
  199.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  200.  
  201.             delete [] buffer;
  202.             return;
  203.         }
  204.     }
  205.  
  206.     ParseCommand();
  207.  
  208.     delete [] buffer;
  209. }
  210.  
  211. BOOL CControlSocket::GetCommand(CStdString &command, CStdString &args)
  212. {
  213.     //Get first command from input buffer
  214.     CStdString str;
  215.     if (m_RecvLineBuffer.empty())
  216.         return FALSE;
  217.     str = m_RecvLineBuffer.front();
  218.     m_RecvLineBuffer.pop_front();
  219.  
  220.     //Output command in status window
  221.     CStdString str2=str;
  222.     str2.MakeUpper();
  223.  
  224.     //Hide passwords if the server admin wants to.
  225.     if (str2.Left(5)=="PASS ")
  226.     {    if (m_pOwner->m_pOptions->GetOptionVal(OPTION_LOGSHOWPASS))
  227.             SendStatus(str,2);
  228.         else
  229.         {
  230.             str2=str.Left(5);
  231.             for (int i=0;i<str.GetLength()-5;i++)
  232.                 str2+="*";
  233.             SendStatus(str2,2);
  234.         }
  235.     }
  236.     else
  237.         SendStatus(str,2);
  238.  
  239.     //Split command and arguments
  240.     int pos = str.Find(" ");
  241.     if (pos!=-1)
  242.     {
  243.         command = str.Left(pos);
  244.         args = str.Mid(pos+1);
  245.         args.TrimLeft(" ");
  246.         args.TrimRight(" ");
  247.     }
  248.     else
  249.         command = str;
  250.     if (command == "")
  251.         return FALSE;
  252.     command.MakeUpper();
  253.     return TRUE;
  254. }
  255.  
  256. void CControlSocket::SendStatus(LPCTSTR status, int type)
  257. {
  258.     t_statusmsg *msg=new t_statusmsg;
  259.     strcpy(msg->ip, m_RemoteIP);
  260.     GetLocalTime(&msg->time);
  261.     if (!m_status.loggedon)
  262.     {
  263.         msg->user = new char[16];
  264.         strcpy(msg->user, "(not logged in)");
  265.     }
  266.     else
  267.     {
  268.         msg->user = new char[strlen(m_status.user)+1];
  269.         strcpy(msg->user, m_status.user);
  270.     }
  271.     msg->userid=m_userid;
  272.     msg->type=type;
  273.     msg->status = new char[strlen(status)+1];
  274.     strcpy(msg->status, status);
  275.     m_pOwner->SendNotification(FSM_STATUSMESSAGE, (LPARAM)msg);
  276. }
  277.  
  278. BOOL CControlSocket::Send(LPCTSTR str, bool sendStatus /*=true*/)
  279. {
  280.     char *buffer = new char[strlen(str) + 3];
  281.     strcpy(buffer, str);
  282.     strcat(buffer, "\r\n");
  283.     int len = strlen(buffer);
  284.  
  285.     if (sendStatus)
  286.         SendStatus(str, 3);
  287.     else if (strlen(str) > 3 && str[3] != '-')
  288.     {
  289.         char buffer[4];
  290.         memcpy(buffer, str, 3);
  291.         buffer[3] = 0;
  292.         SendStatus(buffer, 3);
  293.     }
  294.  
  295.     //Add line to back of send buffer if it's not empty
  296.     if (m_pSendBuffer)
  297.     {
  298.         char *tmp = m_pSendBuffer;
  299.         m_pSendBuffer = new char[m_nSendBufferLen + len];
  300.         memcpy(m_pSendBuffer, tmp, m_nSendBufferLen);
  301.         memcpy(m_pSendBuffer+m_nSendBufferLen, buffer, len);
  302.         delete [] tmp;
  303.         m_nSendBufferLen += len;
  304.         delete [] buffer;
  305.         return TRUE;
  306.     }
  307.  
  308.     int nLimit = GetSpeedLimit(download);
  309.     if (!nLimit)
  310.     {
  311.         if (!m_pSendBuffer)
  312.         {
  313.             m_pSendBuffer = new char[len];
  314.             memcpy(m_pSendBuffer, buffer, len);
  315.             m_nSendBufferLen = len;
  316.         }
  317.         else
  318.         {
  319.             char *tmp = m_pSendBuffer;
  320.             m_pSendBuffer = new char[m_nSendBufferLen + len];
  321.             memcpy(m_pSendBuffer, tmp, m_nSendBufferLen);
  322.             memcpy(m_pSendBuffer+m_nSendBufferLen, buffer, len);
  323.             delete [] tmp;
  324.             m_nSendBufferLen += len;
  325.         }
  326.         delete [] buffer;
  327.         return TRUE;
  328.     }
  329.     int numsend = nLimit;
  330.     if (numsend == -1 || len < numsend)
  331.         numsend = len;
  332.  
  333.     int res = CAsyncSocketEx::Send(buffer, numsend);
  334.     if (res==SOCKET_ERROR && GetLastError() == WSAEWOULDBLOCK)
  335.     {
  336.         res = 0;
  337.     }
  338.     else if (!res || res==SOCKET_ERROR)
  339.     {
  340.         delete [] buffer;
  341.         Close();
  342.         SendStatus("could not send reply, disconnected.",0);
  343.         m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  344.         return FALSE;
  345.     }
  346.  
  347.     if (nLimit != -1)
  348.         m_SlQuotas[download].nTransferred += res;
  349.  
  350.     if (res != len)
  351.     {
  352.         if (!m_pSendBuffer)
  353.         {
  354.             m_pSendBuffer = new char[len-res];
  355.             memcpy(m_pSendBuffer, buffer+res, len-res);
  356.             m_nSendBufferLen = len-res;
  357.         }
  358.         else
  359.         {
  360.             char *tmp = m_pSendBuffer;
  361.             m_pSendBuffer = new char[m_nSendBufferLen + len - res];
  362.             memcpy(m_pSendBuffer, tmp, m_nSendBufferLen);
  363.             memcpy(m_pSendBuffer+m_nSendBufferLen, buffer+res, len-res);
  364.             delete [] tmp;
  365.             m_nSendBufferLen += len-res;
  366.         }
  367.         TriggerEvent(FD_WRITE);
  368.     }
  369.     delete [] buffer;
  370.  
  371.     m_pOwner->IncSendCount(res);
  372.     return TRUE;
  373. }
  374.  
  375. void CControlSocket::OnClose(int nErrorCode)
  376. {
  377.     Close();
  378.     SendStatus("disconnected.",0);
  379.     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  380.     CAsyncSocketEx::OnClose(nErrorCode);
  381. }
  382.  
  383. #define COMMAND_USER    0
  384. #define COMMAND_PASS    1
  385. #define COMMAND_QUIT    2
  386. #define COMMAND_CWD        3
  387. #define COMMAND_PWD        4
  388. #define COMMAND_PORT    5
  389. #define COMMAND_PASV    6
  390. #define COMMAND_TYPE    7
  391. #define COMMAND_LIST    8
  392. #define COMMAND_REST    9
  393. #define COMMAND_CDUP    10
  394. #define COMMAND_RETR    11
  395. #define COMMAND_STOR    12
  396. #define COMMAND_SIZE    13
  397. #define COMMAND_DELE    14
  398. #define COMMAND_RMD        15
  399. #define COMMAND_MKD        16
  400. #define COMMAND_RNFR    17
  401. #define COMMAND_RNTO    18
  402. #define COMMAND_ABOR    19
  403. #define COMMAND_SYST    20
  404. #define COMMAND_NOOP    21
  405. #define COMMAND_APPE    22
  406. #define COMMAND_NLST    23
  407. #define COMMAND_MDTM    24
  408. #define COMMAND_XPWD    25
  409. #define COMMAND_XCUP    26
  410. #define COMMAND_XMKD    27
  411. #define COMMAND_XRMD    28
  412. #define COMMAND_NOP        29
  413. #define COMMAND_EPSV    30
  414. #define COMMAND_EPRT    31
  415. #define COMMAND_AUTH    32
  416. #define COMMAND_ADAT    33
  417. #define COMMAND_PBSZ    34
  418. #define COMMAND_PROT    35
  419. #define COMMAND_FEAT    36
  420. #define COMMAND_MODE    37
  421. #define COMMAND_OPTS    38
  422. #define COMMAND_HELP    39
  423. #define COMMAND_ALLO    40
  424. #define COMMAND_MLST    41
  425. #define COMMAND_MLSD    42
  426.  
  427. typedef struct
  428. {
  429.     int nID;
  430.     char command[5];
  431.     BOOL bHasargs;
  432.     BOOL bValidBeforeLogon;
  433. } t_command;
  434.  
  435. static const t_command commands[]={    COMMAND_USER, "USER", TRUE,     TRUE,
  436.                                     COMMAND_PASS, "PASS", FALSE, TRUE,
  437.                                     COMMAND_QUIT, "QUIT", FALSE, TRUE,
  438.                                     COMMAND_CWD,  "CWD",  TRUE,  FALSE,
  439.                                     COMMAND_PWD,  "PWD",  FALSE, FALSE,
  440.                                     COMMAND_PORT, "PORT", TRUE,  FALSE,
  441.                                     COMMAND_PASV, "PASV", FALSE, FALSE,
  442.                                     COMMAND_TYPE, "TYPE", TRUE,  FALSE,
  443.                                     COMMAND_LIST, "LIST", FALSE, FALSE,
  444.                                     COMMAND_REST, "REST", TRUE,  FALSE,
  445.                                     COMMAND_CDUP, "CDUP", FALSE, FALSE,
  446.                                     COMMAND_RETR, "RETR", TRUE,  FALSE,
  447.                                     COMMAND_STOR, "STOR", TRUE,  FALSE,
  448.                                     COMMAND_SIZE, "SIZE", TRUE,  FALSE,
  449.                                     COMMAND_DELE, "DELE", TRUE,  FALSE,
  450.                                     COMMAND_RMD,  "RMD",  TRUE,  FALSE,
  451.                                     COMMAND_MKD,  "MKD",  TRUE,  FALSE,
  452.                                     COMMAND_RNFR, "RNFR", TRUE,  FALSE,
  453.                                     COMMAND_RNTO, "RNTO", TRUE,  FALSE,
  454.                                     COMMAND_ABOR, "ABOR", FALSE, FALSE,
  455.                                     COMMAND_SYST, "SYST", FALSE, TRUE,
  456.                                     COMMAND_NOOP, "NOOP", FALSE, FALSE,
  457.                                     COMMAND_APPE, "APPE", TRUE,  FALSE,
  458.                                     COMMAND_NLST, "NLST", FALSE, FALSE,
  459.                                     COMMAND_MDTM, "MDTM", TRUE,  FALSE,
  460.                                     COMMAND_XPWD, "XPWD", FALSE, FALSE,
  461.                                     COMMAND_XCUP, "XCUP", FALSE, FALSE,
  462.                                     COMMAND_XMKD, "XMKD", TRUE,  FALSE,
  463.                                     COMMAND_XRMD, "XRMD", TRUE,  FALSE,
  464.                                     COMMAND_NOP,  "NOP",  FALSE, FALSE,
  465.                                     COMMAND_EPSV, "EPSV", FALSE, FALSE,
  466.                                     COMMAND_EPRT, "EPRT", TRUE,  FALSE,
  467.                                     COMMAND_AUTH, "AUTH", TRUE,  TRUE,
  468.                                     COMMAND_ADAT, "ADAT", TRUE,  TRUE,
  469.                                     COMMAND_PBSZ, "PBSZ", TRUE,  TRUE,
  470.                                     COMMAND_PROT, "PROT", TRUE,  TRUE,
  471.                                     COMMAND_FEAT, "FEAT", FALSE, TRUE,
  472.                                     COMMAND_MODE, "MODE", TRUE,  FALSE,
  473.                                     COMMAND_OPTS, "OPTS", TRUE,  FALSE,
  474.                                     COMMAND_HELP, "HELP", FALSE, TRUE,
  475.                                     COMMAND_ALLO, "ALLO", FALSE, FALSE,
  476.                                     COMMAND_MLST, "MLST", FALSE, FALSE,
  477.                                     COMMAND_MLSD, "MLSD", FALSE, FALSE
  478.                         };
  479.  
  480. void CControlSocket::ParseCommand()
  481. {
  482.     if (m_antiHammeringWaitTime)
  483.         return;
  484.  
  485.     //Get command
  486.     CStdString command, args;
  487.     if (!GetCommand(command, args))
  488.         return;
  489.  
  490.     //Check if command is valid
  491.     int nCommandID = -1;
  492.     for (int i = 0; i < (sizeof(commands)/sizeof(t_command)); i++)
  493.     {
  494.         if (command == commands[i].command)
  495.         {
  496.             //Does the command needs an argument?
  497.             if (commands[i].bHasargs && (args==""))
  498.             {
  499.                 Send("501 Syntax error");
  500.                 if (!m_RecvLineBuffer.empty())
  501.                     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  502.                 return;
  503.             }
  504.             //Can it be issued before logon?
  505.             else if (!m_status.loggedon && !commands[i].bValidBeforeLogon)
  506.             {
  507.                 Send("530 Please log in with USER and PASS first.");
  508.                 if (!m_RecvLineBuffer.empty())
  509.                     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  510.                 return;
  511.             }
  512.             nCommandID = commands[i].nID;
  513.             break;
  514.         }
  515.     }
  516.     //Command not recognized
  517.     if (nCommandID == -1)
  518.     {
  519.         Send("500 Syntax error, command unrecognized.");
  520.         if (!m_RecvLineBuffer.empty())
  521.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  522.         return;
  523.     }
  524.  
  525.     //Now process the commands
  526.     switch (nCommandID)
  527.     {
  528.     case COMMAND_USER:
  529.         {
  530.             AntiHammerIncrease();
  531.             if (m_status.loggedon)
  532.             {
  533.                 GetSystemTime(&m_LoginTime);
  534.                 DecUserCount(m_status.user);
  535.                 m_pOwner->DecIpCount(m_status.ip);
  536.                 t_connop *op = new t_connop;
  537.                 op->op = USERCONTROL_CONNOP_CHANGEUSER;
  538.                 t_connectiondata_changeuser *conndata = new t_connectiondata_changeuser;
  539.                 op->data = conndata;
  540.                 op->userid = m_userid;
  541.                 m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  542.  
  543.                 m_status.loggedon = FALSE;
  544.                 m_CurrentServerDir = "";
  545.             }
  546.             if (m_pOwner->m_pOptions->GetOptionVal(OPTION_ENABLESSL) && m_pOwner->m_pOptions->GetOptionVal(OPTION_ALLOWEXPLICITSSL) &&
  547.                 m_pOwner->m_pOptions->GetOptionVal(OPTION_SSLFORCEEXPLICIT) && !m_pSslLayer)
  548.             {
  549.                 Send("530 Have to use explicit SSL/TLS before logging on.");
  550.                 break;
  551.             }
  552.             RenName = "";
  553.             args.MakeLower();
  554.             m_status.user = args;
  555.             if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  556.             {
  557.                 char sendme[4096];
  558.  
  559.                 int res = m_pGssLayer->ProcessCommand("USER", args, sendme);
  560.                 if (res != -1)
  561.                 {
  562.                     if (DoUserLogin("", true))
  563.                         Send(sendme);
  564.                 }
  565.                 break;
  566.             }
  567.             if (!m_pSslLayer)
  568.             {
  569.                 CUser user;
  570.                 if (m_pOwner->m_pPermissions->CheckUserLogin(m_status.user, "", user, true) && user.ForceSsl())
  571.                 {
  572.                     Send("530 SSL required");
  573.                     break;
  574.                 }
  575.             }
  576.             Send("331 Password required for "+args);
  577.         }
  578.         break;
  579.     case COMMAND_PASS:
  580.         AntiHammerIncrease();
  581.         if (m_status.loggedon)
  582.             Send("503 Bad sequence of commands.");
  583.         else if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  584.         {
  585.             char sendme[4096];
  586.             int res = m_pGssLayer->ProcessCommand("PASS", m_status.user, args, sendme);
  587.             if (res != -1)
  588.             {
  589.                 if (DoUserLogin("", true))
  590.                     Send(sendme);
  591.             }
  592.         }
  593.         else if (DoUserLogin(args))
  594.             Send("230 Logged on");
  595.         break;
  596.     case COMMAND_QUIT:
  597.         m_bQuitCommand = TRUE;
  598.         if (!m_transferstatus.socket)            
  599.         {
  600.             Send(_T("221 Goodbye"));
  601.             if (m_pSslLayer)
  602.             {
  603.                 if (ShutDown() || WSAGetLastError() != WSAEWOULDBLOCK)
  604.                     ForceClose(5);
  605.             }
  606.             else if (CanQuit())
  607.                 ForceClose(5);
  608.         }
  609.         break;
  610.     case COMMAND_CWD:
  611.         {
  612.             //Unquote args
  613.             if (!UnquoteArgs(args))
  614.             {
  615.                 Send(_T("501 Syntax error"));
  616.                 break;
  617.             }
  618.  
  619.             int res = m_pOwner->m_pPermissions->ChangeCurrentDir(m_status.user, m_CurrentServerDir, args);
  620.             if (!res)
  621.             {
  622.                 CStdString str;
  623.                 str.Format("250 CWD successful. \"%s\" is current directory.", m_CurrentServerDir);
  624.                 Send(str);
  625.             }
  626.             else if (res & PERMISSION_DENIED)
  627.             {
  628.                 CStdString str;
  629.                 str.Format("550 CWD failed. \"%s\": Permission denied.", args);
  630.                 Send(str);
  631.             }
  632.             else if (res & PERMISSION_INVALIDNAME)
  633.             {
  634.                 CStdString str;
  635.                 str.Format("550 CWD failed. \"%s\": Filename invalid.", args);
  636.                 Send(str);
  637.             }
  638.             else if (res)
  639.             {
  640.                 CStdString str;
  641.                 str.Format("550 CWD failed. \"%s\": directory not found.", args);
  642.                 Send(str);
  643.             }
  644.         }
  645.         break;
  646.     case COMMAND_PWD:
  647.     case COMMAND_XPWD:
  648.         {
  649.             CStdString str;
  650.             str.Format("257 \"%s\" is current directory.", m_CurrentServerDir);
  651.             Send(str);
  652.         }
  653.         break;
  654.     case COMMAND_PORT:
  655.         {
  656.             if (m_transferstatus.socket)
  657.             {
  658.                 SendTransferinfoNotification();
  659.                 delete m_transferstatus.socket;
  660.                 m_transferstatus.socket=0;
  661.             }
  662.             int count=0;
  663.             int pos=0;
  664.             //Convert commas to dots
  665.             args.Replace(",",".");
  666.             while(1)
  667.             {
  668.                 pos=args.Find(".",pos);
  669.                 if (pos!=-1)
  670.                     count++;
  671.                 else
  672.                     break;
  673.                 pos++;
  674.             }
  675.             if (count!=5)
  676.             {
  677.                 Send("501 Syntax error");
  678.                 break;
  679.             }
  680.             CStdString ip;
  681.             int port = 0;
  682.             int i=args.ReverseFind('.');
  683.             port=atoi(args.Right(args.GetLength()-(i+1))); //get ls byte of server socket
  684.             args=args.Left(i);
  685.             i=args.ReverseFind('.');
  686.             port+=256*atoi(args.Right(args.GetLength()-(i+1))); // add ms byte to server socket
  687.             ip=args.Left(i);
  688.  
  689.             int res = inet_addr(ip);
  690.             if (res == INADDR_NONE)
  691.             {
  692.                 // Fix: Convert IP in PORT command to int and back to string (strips
  693.                 // leading zeros) because some FTP clients prepend zeros to it.
  694.                 // inet_addr() thinks this is an octal number and will return INADDR_NONE
  695.                 // if 8 or 9 are encountered.
  696.                 CStdString decIP;
  697.                 ip += ".";
  698.                 int pos = ip.Find('.');
  699.                 while (pos != -1)
  700.                 {
  701.                     CStdString tmp;
  702.                     tmp.Format("%d.", atoi(ip.Left(pos)));
  703.                     decIP += tmp;
  704.  
  705.                     ip = ip.Mid(pos + 1);
  706.                     pos = ip.Find('.');
  707.                 }
  708.  
  709.                 ip = decIP.Left(decIP.GetLength() - 1);
  710.                 res = inet_addr(ip);
  711.             }
  712.  
  713.             if (res == INADDR_NONE || port < 1 || port > 65535)
  714.              {
  715.                 Send("501 Syntax error");
  716.                 break;
  717.             }
  718.  
  719.             m_transferstatus.ip = ip;
  720.             m_transferstatus.port = port;
  721.             m_transferstatus.pasv=0;
  722.             Send("200 Port command successful");
  723.             break;
  724.         }
  725.     case COMMAND_PASV:
  726.         {
  727.             if (m_transferstatus.socket)
  728.             {
  729.                 SendTransferinfoNotification();
  730.                 delete m_transferstatus.socket;
  731.             }
  732.             m_transferstatus.socket = new CTransferSocket(this);
  733.  
  734.             unsigned int port = 0;
  735.             CStdString ip;
  736.             unsigned int retries = 3;
  737.             if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
  738.                 ip = m_pOwner->GetExternalIP();
  739.  
  740.             if (ip == "")
  741.             {
  742.                 //Get the ip of the control socket
  743.                 SOCKADDR_IN sockAddr;
  744.                 memset(&sockAddr, 0, sizeof(sockAddr));
  745.  
  746.                 int nSockAddrLen = sizeof(sockAddr);
  747.                 BOOL bResult = GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  748.                 if (bResult)
  749.                     ip = inet_ntoa(sockAddr.sin_addr);
  750.  
  751.             }
  752.  
  753.             while (retries > 0)
  754.             {
  755.                 if (m_pOwner->m_pOptions->GetOptionVal(OPTION_USECUSTOMPASVPORT))
  756.                 {
  757.                     static UINT customPort = 0;
  758.                     unsigned int minPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMINPORT);
  759.                     unsigned int maxPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMAXPORT);
  760.                     if (minPort > maxPort) {
  761.                         unsigned int temp = minPort;
  762.                         minPort = maxPort;
  763.                         maxPort = temp;
  764.                     }
  765.                     if (customPort < minPort || customPort > maxPort) {
  766.                         customPort = minPort;
  767.                     }
  768.                     port = customPort;
  769.  
  770.                     ++customPort;
  771.                 } else {
  772.                     port = 0;
  773.                 }
  774.                 if (m_transferstatus.socket->Create(port, SOCK_STREAM, FD_ACCEPT))
  775.                     break;
  776.                 --retries;
  777.             }
  778.             if (retries <= 0) {
  779.                 delete m_transferstatus.socket;
  780.                 m_transferstatus.socket = NULL;
  781.                 Send("421 Can't create socket");
  782.                 break;
  783.             }
  784.  
  785.             if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  786.                 m_transferstatus.socket->UseGSS(m_pGssLayer);
  787.  
  788.             if (m_pSslLayer && m_bProtP)
  789.                 m_transferstatus.socket->UseSSL(new CAsyncSslSocketLayer(), m_pSslLayer->GetContext());
  790.  
  791.             if (!m_transferstatus.socket->Listen())
  792.             {
  793.                 delete m_transferstatus.socket;
  794.                 m_transferstatus.socket = NULL;
  795.                 Send("421 Can't create socket");
  796.                 break;
  797.             }
  798.  
  799.             //Now retrieve the port
  800.             SOCKADDR_IN sockAddr;
  801.             memset(&sockAddr, 0, sizeof(sockAddr));
  802.  
  803.             int nSockAddrLen = sizeof(sockAddr);
  804.             BOOL bResult = m_transferstatus.socket->GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  805.             if (bResult)
  806.                 port = ntohs(sockAddr.sin_port);
  807.             //Reformat the ip
  808.             ip.Replace(".",",");
  809.             //Put the answer together
  810.             CStdString str;
  811.             str.Format("227 Entering Passive Mode (%s,%d,%d)",ip,port/256,port%256);
  812.             Send(str);
  813.             m_transferstatus.pasv=1;
  814.             break;
  815.         }
  816.     case COMMAND_TYPE:
  817.         {
  818.             args.MakeUpper();
  819.             if (args[0] != 'I' && args[0] != 'A')
  820.             {
  821.                 Send("501 Parameters invalid. Must be I for binary and A for ASCII type.");
  822.                 break;
  823.             }
  824.             m_transferstatus.type=(args[0]=='I')?0:1;
  825.             Send(CStdString("200 Type set to ") + (m_transferstatus.type ? "A" : "I"));
  826.         }
  827.         break;
  828.     case COMMAND_LIST:
  829.         if (m_transferstatus.pasv == -1)
  830.         {
  831.             Send("503 Bad sequence of commands.");
  832.             break;
  833.         }
  834.         if (!m_transferstatus.pasv && (m_transferstatus.ip == "" || m_transferstatus.port == -1))
  835.         {
  836.             Send("503 Bad sequence of commands.");
  837.             break;
  838.         }
  839.         if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  840.         {
  841.             Send(_T("550 PROT P required"));
  842.             break;
  843.         }
  844.         else
  845.         {
  846.             //Check args, currently only supported argument is the directory which will be listed.
  847.             CStdString dirToList;
  848.             args.TrimLeft(" ");
  849.             args.TrimRight(" ");
  850.             if (args!="")
  851.             {
  852.                 BOOL bBreak = FALSE;
  853.                 while (args[0] == '-') //No parameters supported
  854.                 {
  855.                     if (args.GetLength() < 2)
  856.                     { //Dash without param
  857.                         Send("501 Syntax error");
  858.                         bBreak = TRUE;
  859.                         break;
  860.                     }
  861.  
  862.                     int pos = args.Find(" ");
  863.                     CStdString params;
  864.                     if (pos!=-1)
  865.                     {
  866.                         params = args.Left(1);
  867.                         params = params.Left(pos-1);
  868.                         args = args.Mid(pos+1);
  869.                         args.TrimLeft(" ");
  870.                     }
  871.                     else
  872.                         args = "";
  873.                     while (params != "")
  874.                     {
  875.                         //Some parameters are not support
  876.                         if (params[0]=='R')
  877.                         {
  878.                             Send("504 Command not implemented for that parameter");
  879.                             bBreak = TRUE;
  880.                             break;
  881.                         }
  882.                         //Ignore other parameters
  883.                         params=params.Mid(1);
  884.                     }
  885.  
  886.                     if (args=="")
  887.                         break;
  888.                 }
  889.                 if (bBreak)
  890.                     break;
  891.                 if (args != "")
  892.                 {
  893.                     //Unquote args
  894.                     if (!UnquoteArgs(args))
  895.                     {
  896.                         Send(_T("501 Syntax error"));
  897.                         break;
  898.                     }
  899.  
  900.                     dirToList = args;
  901.                 }
  902.             }
  903.  
  904.             t_dirlisting *pResult;
  905.             CStdString physicalDir, logicalDir;
  906.             int error = m_pOwner->m_pPermissions->GetDirectoryListing(m_status.user, m_CurrentServerDir, dirToList, pResult, physicalDir, logicalDir);
  907.             if (error & PERMISSION_DENIED)
  908.             {
  909.                 Send("550 Permission denied.");
  910.                 ResetTransferstatus();
  911.                 break;
  912.             }
  913.             else if (error & PERMISSION_INVALIDNAME)
  914.             {
  915.                 Send("550 Filename invalid.");
  916.                 ResetTransferstatus();
  917.                 break;
  918.             }
  919.             else if (error)
  920.             {
  921.                 Send("550 Directory not found.");
  922.                 ResetTransferstatus();
  923.                 break;
  924.             }
  925.  
  926.             if (!m_transferstatus.pasv)
  927.             {
  928.                 if (m_transferstatus.socket)
  929.                 {
  930.                     SendTransferinfoNotification();
  931.                     delete m_transferstatus.socket;
  932.                 }
  933.                 CTransferSocket *transfersocket = new CTransferSocket(this);
  934.                 m_transferstatus.socket = transfersocket;
  935.                 transfersocket->Init(pResult, TRANSFERMODE_LIST);
  936.                 if (m_transferMode == mode_zlib)
  937.                 {
  938.                     if (!transfersocket->InitZLib(m_zlibLevel))
  939.                     {
  940.                         Send("550 could not initialize zlib, please use MODE S instead");
  941.                         ResetTransferstatus();
  942.                         break;
  943.                     }
  944.                 }
  945.  
  946.                 if (!CreateTransferSocket(transfersocket))
  947.                     break;
  948.  
  949.                 SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir);
  950.                 Send("150 Opening data channel for directory list.");
  951.             }
  952.             else
  953.             {
  954.                 m_transferstatus.socket->Init(pResult, TRANSFERMODE_LIST);
  955.                 if (m_transferMode == mode_zlib)
  956.                 {
  957.                     if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  958.                     {
  959.                         Send("550 could not initialize zlib, please use MODE S instead");
  960.                         ResetTransferstatus();
  961.                         break;
  962.                     }
  963.                 }
  964.  
  965.                 SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir);
  966.                 m_transferstatus.socket->PasvTransfer();
  967.             }
  968.         }
  969.         break;
  970.     case COMMAND_REST:
  971.         {
  972.             BOOL error=FALSE;
  973.             for (int i=0;i<args.GetLength();i++)
  974.                 if (!isdigit(args[i]))
  975.                     error=TRUE;
  976.             if (error)
  977.             {
  978.                 Send("501 Bad parameter. Numeric value required");
  979.                 break;
  980.             }
  981.             m_transferstatus.rest=_atoi64(args);
  982.             CStdString str;
  983.             str.Format("350 Rest supported. Restarting at %I64d",m_transferstatus.rest);
  984.             Send(str);
  985.         }
  986.         break;
  987.     case COMMAND_CDUP:
  988.     case COMMAND_XCUP:
  989.         {
  990.             CStdString dir = "..";
  991.             int res = m_pOwner->m_pPermissions->ChangeCurrentDir(m_status.user, m_CurrentServerDir, dir);
  992.             if (!res)
  993.             {
  994.                 CStdString str;
  995.                 str.Format("200 CDUP successful. \"%s\" is current directory.", m_CurrentServerDir);
  996.                 Send(str);
  997.             }
  998.             else if (res & PERMISSION_DENIED)
  999.                 Send("550 CDUP failed, permission denied.");
  1000.             else if (res & PERMISSION_INVALIDNAME)
  1001.                 Send("550 CDUP failed, filename invalid.");
  1002.             else if (res)
  1003.                 Send("550 CDUP failed, directory not found.");
  1004.         }
  1005.         break;
  1006.     case COMMAND_RETR:
  1007.         {
  1008.             if (m_transferstatus.pasv == -1)
  1009.             {
  1010.                 Send("503 Bad sequence of commands.");
  1011.                 break;
  1012.             }
  1013.             if (!m_transferstatus.pasv && (m_transferstatus.ip == "" || m_transferstatus.port == -1))
  1014.             {
  1015.                 Send("503 Bad sequence of commands.");
  1016.                 break;
  1017.             }
  1018.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1019.             {
  1020.                 Send(_T("550 PROT P required"));
  1021.                 break;
  1022.             }
  1023.             //Much more checks
  1024.  
  1025.             //Unquote args
  1026.             if (!UnquoteArgs(args))
  1027.             {
  1028.                 Send( _T("501 Syntax error") );
  1029.                 break;
  1030.             }
  1031.  
  1032.  
  1033.             CStdString physicalFile, logicalFile;
  1034.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_READ, physicalFile, logicalFile);
  1035.             if (error & PERMISSION_DENIED)
  1036.             {
  1037.                 Send("550 Permission denied");
  1038.                 ResetTransferstatus();
  1039.             }
  1040.             else if (error & PERMISSION_INVALIDNAME)
  1041.             {
  1042.                 Send("550 Filename invalid.");
  1043.                 ResetTransferstatus();
  1044.             }
  1045.             else if (error)
  1046.             {
  1047.                 Send("550 File not found");
  1048.                 ResetTransferstatus();
  1049.             }
  1050.             else
  1051.             {
  1052.                 if (!m_transferstatus.pasv)
  1053.                 {
  1054.                     if (m_transferstatus.socket)
  1055.                     {
  1056.                         SendTransferinfoNotification();
  1057.                         delete m_transferstatus.socket;
  1058.                     }
  1059.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1060.                     m_transferstatus.socket = transfersocket;
  1061.                     transfersocket->Init(physicalFile, TRANSFERMODE_SEND, m_transferstatus.rest);
  1062.                     if (m_transferMode == mode_zlib)
  1063.                     {
  1064.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1065.                         {
  1066.                             Send("550 could not initialize zlib, please use MODE S instead");
  1067.                             ResetTransferstatus();
  1068.                             break;
  1069.                         }
  1070.                     }
  1071.  
  1072.                     if (!CreateTransferSocket(transfersocket))
  1073.                         break;
  1074.  
  1075.                     __int64 totalSize;
  1076.                     if (!GetLength64(physicalFile, totalSize))
  1077.                         totalSize = -1;
  1078.                     SendTransferinfoNotification(TRANSFERMODE_SEND, physicalFile, logicalFile, m_transferstatus.rest, totalSize);
  1079.  
  1080.                     Send("150 Opening data channel for file transfer.");
  1081.                 }
  1082.                 else
  1083.                 {
  1084.                     m_transferstatus.socket->Init(physicalFile, TRANSFERMODE_SEND, m_transferstatus.rest);
  1085.                     if (m_transferMode == mode_zlib)
  1086.                     {
  1087.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1088.                         {
  1089.                             Send("550 could not initialize zlib, please use MODE S instead");
  1090.                             ResetTransferstatus();
  1091.                             break;
  1092.                         }
  1093.                     }
  1094.  
  1095.                     __int64 totalSize;
  1096.                     if (!GetLength64(physicalFile, totalSize))
  1097.                         totalSize = -1;
  1098.                     SendTransferinfoNotification(TRANSFERMODE_SEND, physicalFile, logicalFile, m_transferstatus.rest, totalSize);
  1099.  
  1100.                     m_transferstatus.socket->PasvTransfer();
  1101.                 }
  1102.                 GetSystemTime(&m_LastTransferTime);
  1103.             }
  1104.             break;
  1105.         }
  1106.     case COMMAND_STOR:
  1107.         {
  1108.             if(m_transferstatus.pasv==-1)
  1109.             {
  1110.                 Send("503 Bad sequence of commands.");
  1111.                 break;
  1112.             }
  1113.             if(!m_transferstatus.pasv && (m_transferstatus.ip=="" || m_transferstatus.port==-1))
  1114.             {
  1115.                 Send("503 Bad sequence of commands.");
  1116.                 break;
  1117.             }
  1118.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1119.             {
  1120.                 Send(_T("550 PROT P required"));
  1121.                 break;
  1122.             }
  1123.             //Much more checks
  1124.  
  1125.             //Unquote args
  1126.             if (!UnquoteArgs(args))
  1127.             {
  1128.                 Send( _T("501 Syntax error") );
  1129.                 break;
  1130.             }
  1131.  
  1132.             CStdString physicalFile, logicalFile;
  1133.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, m_transferstatus.rest ? FOP_APPEND : FOP_WRITE, physicalFile, logicalFile);
  1134.             if (error & PERMISSION_DENIED)
  1135.             {
  1136.                 Send("550 Permission denied");
  1137.                 ResetTransferstatus();
  1138.             }
  1139.             else if (error & PERMISSION_INVALIDNAME)
  1140.             {
  1141.                 Send("550 Filename invalid.");
  1142.                 ResetTransferstatus();
  1143.             }
  1144.             else if (error)
  1145.             {
  1146.                 Send("550 Filename invalid");
  1147.                 ResetTransferstatus();
  1148.             }
  1149.             else
  1150.             {
  1151.                 if (!m_transferstatus.pasv)
  1152.                 {
  1153.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1154.                     transfersocket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1155.                     m_transferstatus.socket = transfersocket;
  1156.                     if (m_transferMode == mode_zlib)
  1157.                     {
  1158.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1159.                         {
  1160.                             Send("550 could not initialize zlib, please use MODE S instead");
  1161.                             ResetTransferstatus();
  1162.                             break;
  1163.                         }
  1164.                     }
  1165.  
  1166.                     if (!CreateTransferSocket(transfersocket))
  1167.                         break;
  1168.  
  1169.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1170.                     Send("150 Opening data channel for file transfer.");
  1171.                 }
  1172.                 else
  1173.                 {
  1174.                     m_transferstatus.socket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1175.                     if (m_transferMode == mode_zlib)
  1176.                     {
  1177.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1178.                         {
  1179.                             Send("550 could not initialize zlib, please use MODE S instead");
  1180.                             ResetTransferstatus();
  1181.                             break;
  1182.                         }
  1183.                     }
  1184.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1185.                     m_transferstatus.socket->PasvTransfer();
  1186.                 }
  1187.                 GetSystemTime(&m_LastTransferTime);
  1188.             }
  1189.         }
  1190.         break;
  1191.     case COMMAND_SIZE:
  1192.         {
  1193.             //Unquote args
  1194.             if (!UnquoteArgs(args))
  1195.             {
  1196.                 Send( _T("501 Syntax error") );
  1197.                 break;
  1198.             }
  1199.  
  1200.             CStdString physicalFile, logicalFile;
  1201.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_READ, physicalFile, logicalFile);
  1202.             if (error & PERMISSION_DENIED)
  1203.                 Send("550 Permission denied");
  1204.             else if (error & PERMISSION_INVALIDNAME)
  1205.                 Send("550 Filename invalid.");
  1206.             else if (error)
  1207.                 Send("550 File not found");
  1208.             else
  1209.             {
  1210.                 CStdString str;
  1211.                 _int64 length;
  1212.                 if (GetLength64(physicalFile, length))
  1213.                     str.Format("213 %I64d", length);
  1214.                 else
  1215.                     str = "550 File not found";
  1216.                 Send(str);
  1217.             }
  1218.         }
  1219.         break;
  1220.     case COMMAND_DELE:
  1221.         {
  1222.             //Unquote args
  1223.             if (!UnquoteArgs(args))
  1224.             {
  1225.                 Send( _T("501 Syntax error") );
  1226.                 break;
  1227.             }
  1228.  
  1229.             CStdString physicalFile, logicalFile;
  1230.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_DELETE, physicalFile, logicalFile);
  1231.             if (error & PERMISSION_DENIED)
  1232.                 Send("550 Permission denied");
  1233.             else if (error & PERMISSION_INVALIDNAME)
  1234.                 Send("550 Filename invalid.");
  1235.             else if (error)
  1236.                 Send("550 File not found");
  1237.             else
  1238.             {
  1239.                 if (!DeleteFile(physicalFile))
  1240.                     Send(_T("450 Internal error deleting the file."));
  1241.                 else
  1242.                     Send(_T("250 File deleted successfully"));
  1243.             }
  1244.         }
  1245.         break;
  1246.     case COMMAND_RMD:
  1247.     case COMMAND_XRMD:
  1248.         {
  1249.             //Unquote args
  1250.             if (!UnquoteArgs(args))
  1251.             {
  1252.                 Send( _T("501 Syntax error") );
  1253.                 break;
  1254.             }
  1255.  
  1256.             CStdString physicalFile, logicalFile;
  1257.             int error = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args, m_CurrentServerDir, DOP_DELETE, physicalFile, logicalFile);
  1258.             if (error & PERMISSION_DENIED)
  1259.                 Send("550 Permission denied");
  1260.             else if (error & PERMISSION_INVALIDNAME)
  1261.                 Send("550 Filename invalid.");
  1262.             else if (error)
  1263.                 Send("550 Directory not found");
  1264.             else
  1265.             {
  1266.                 if (!RemoveDirectory(physicalFile))
  1267.                 {
  1268.                     if (GetLastError() == ERROR_DIR_NOT_EMPTY)
  1269.                         Send("550 Directory not empty.");
  1270.                     else
  1271.                         Send("450 Internal error deleting the directory.");
  1272.                 }
  1273.                 else
  1274.                     Send("250 Directory deleted successfully");
  1275.             }
  1276.         }
  1277.         break;
  1278.     case COMMAND_MKD:
  1279.     case COMMAND_XMKD:
  1280.         {
  1281.             //Unquote args
  1282.             if (!UnquoteArgs(args))
  1283.             {
  1284.                 Send( _T("501 Syntax error") );
  1285.                 break;
  1286.             }
  1287.  
  1288.             CStdString physicalFile, logicalFile;
  1289.             int error = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args, m_CurrentServerDir, DOP_CREATE, physicalFile, logicalFile);
  1290.             if (error & PERMISSION_DENIED)
  1291.                 Send("550 Can't create directory. Permission denied");
  1292.             else if (error & PERMISSION_INVALIDNAME)
  1293.                 Send("550 Filename invalid.");
  1294.             else if (error & PERMISSION_DOESALREADYEXIST && (error & PERMISSION_FILENOTDIR)!=PERMISSION_FILENOTDIR)
  1295.                 Send("550 Directory already exists");
  1296.             else if (error & PERMISSION_FILENOTDIR)
  1297.                 Send("550 File with same name already exists");
  1298.             else if (error)
  1299.                 Send("550 Directoryname not valid");
  1300.             else
  1301.             {
  1302.                 CStdString str;
  1303.                 BOOL res = FALSE;
  1304.                 BOOL bReplySent = FALSE;
  1305.                 physicalFile += "\\";
  1306.                 while (physicalFile != "")
  1307.                 {
  1308.                     CStdString piece = physicalFile.Left(physicalFile.Find("\\")+1);
  1309.                     if (piece.Right(2) == ".\\")
  1310.                     {
  1311.                         Send("550 Directoryname not valid");
  1312.                         bReplySent = TRUE;
  1313.                         break;
  1314.                     }
  1315.                     str += piece;
  1316.                     physicalFile = physicalFile.Mid(physicalFile.Find("\\") + 1);
  1317.                     res = CreateDirectory(str, 0);
  1318.                 }
  1319.                 if (!bReplySent)
  1320.                     if (!res)//CreateDirectory(result+"\\",0))
  1321.                     {
  1322.                         int error = GetLastError();
  1323.                         if (error == ERROR_ALREADY_EXISTS)
  1324.                             Send("550 Directory already exists");
  1325.                         else
  1326.                             Send("450 Internal error creating the directory.");
  1327.                     }
  1328.                     else
  1329.                         Send("257 Directory created successfully");
  1330.             }
  1331.         }
  1332.         break;
  1333.     case COMMAND_RNFR:
  1334.         {
  1335.             //Unquote args
  1336.             if (!UnquoteArgs(args))
  1337.             {
  1338.                 Send( _T("501 Syntax error") );
  1339.                 break;
  1340.             }
  1341.  
  1342.             RenName = "";
  1343.  
  1344.             CStdString physicalFile, logicalFile;
  1345.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_DELETE, physicalFile, logicalFile);
  1346.             if (!error)
  1347.             {
  1348.                 RenName = physicalFile;
  1349.                 bRenFile = TRUE;
  1350.                 Send("350 File exists, ready for destination name.");
  1351.                 break;
  1352.             }
  1353.             else if (error & PERMISSION_DENIED)
  1354.                 Send("550 Permission denied");
  1355.             else if (error & PERMISSION_INVALIDNAME)
  1356.                 Send("550 Filename invalid.");
  1357.             else
  1358.             {
  1359.                 int error2 = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args,m_CurrentServerDir, DOP_DELETE, physicalFile, logicalFile);
  1360.                 if (!error2)
  1361.                 {
  1362.                     RenName = physicalFile;
  1363.                     bRenFile = FALSE;
  1364.                     Send("350 Directory exists, ready for destination name.");
  1365.                 }
  1366.                 else if (error2 & PERMISSION_DENIED)
  1367.                     Send("550 Permission denied");
  1368.                 else if (error2 & PERMISSION_INVALIDNAME)
  1369.                     Send("550 Filename invalid.");
  1370.                 else
  1371.                     Send("550 file/directory not found");
  1372.                 break;
  1373.             }
  1374.         }
  1375.         break;
  1376.     case COMMAND_RNTO:
  1377.         {
  1378.             if (RenName=="")
  1379.             {
  1380.                 Send("503 Bad sequence of commands!");
  1381.                 break;
  1382.             }
  1383.  
  1384.             //Unquote args
  1385.             if (!UnquoteArgs(args))
  1386.             {
  1387.                 Send( _T("501 Syntax error") );
  1388.                 break;
  1389.             }
  1390.  
  1391.             if (bRenFile)
  1392.             {
  1393.                 CStdString physicalFile, logicalFile;
  1394.                 int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_CREATENEW, physicalFile, logicalFile);
  1395.                 if (error)
  1396.                     RenName = "";
  1397.                 if (error & PERMISSION_DENIED)
  1398.                     Send("550 Permission denied");
  1399.                 else if (error & PERMISSION_INVALIDNAME)
  1400.                     Send("550 Filename invalid.");
  1401.                 else if (error & PERMISSION_DOESALREADYEXIST && (error & PERMISSION_DIRNOTFILE)!=PERMISSION_DIRNOTFILE)
  1402.                     Send("550 file exists");
  1403.                 else if (error)
  1404.                     Send("550 Filename invalid");
  1405.                 else
  1406.                 {
  1407.                     if (!MoveFile(RenName, physicalFile))
  1408.                         Send("450 Internal error renaming the file");
  1409.                     else
  1410.                         Send("250 file renamed successfully");
  1411.                 }
  1412.             }
  1413.             else
  1414.             {
  1415.                 CStdString physicalFile, logicalFile;
  1416.                 int error = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args, m_CurrentServerDir, DOP_CREATE, physicalFile, logicalFile);
  1417.                 if (error)
  1418.                     RenName = "";
  1419.                 if (error & PERMISSION_DENIED)
  1420.                     Send("550 Permission denied");
  1421.                 else if (error & PERMISSION_INVALIDNAME)
  1422.                     Send("550 Filename invalid.");
  1423.                 else if (error & PERMISSION_DOESALREADYEXIST && (error & PERMISSION_FILENOTDIR)!=PERMISSION_FILENOTDIR)
  1424.                     Send("550 file exists");
  1425.                 else if (error)
  1426.                     Send("550 Filename invalid");
  1427.                 else
  1428.                 {
  1429.                     if (!MoveFile(RenName, physicalFile))
  1430.                         Send("450 Internal error renaming the file");
  1431.                     else
  1432.                         Send("250 file renamed successfully");
  1433.                 }
  1434.             }
  1435.         }
  1436.         break;
  1437.     case COMMAND_ABOR:
  1438.         {
  1439.             if (m_transferstatus.socket)
  1440.             {
  1441.                 if (m_transferstatus.socket->Started())
  1442.                     Send("426 Connection closed; transfer aborted.");
  1443.             }
  1444.             Send("226 ABOR command successful");
  1445.             ResetTransferstatus();
  1446.         break;
  1447.         }
  1448.     case COMMAND_SYST:
  1449.         Send("215 UNIX emulated by FileZilla");
  1450.         break;
  1451.     case COMMAND_NOOP:
  1452.     case COMMAND_NOP:
  1453.         Send("200 OK");
  1454.         break;
  1455.     case COMMAND_APPE:
  1456.         {
  1457.             if(m_transferstatus.pasv==-1)
  1458.             {
  1459.                 Send("503 Bad sequence of commands.");
  1460.                 break;
  1461.             }
  1462.             if(!m_transferstatus.pasv && (m_transferstatus.ip=="" || m_transferstatus.port==-1))
  1463.             {
  1464.                 Send("503 Bad sequence of commands.");
  1465.                 break;
  1466.             }
  1467.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1468.             {
  1469.                 Send(_T("550 PROT P required"));
  1470.                 break;
  1471.             }
  1472.             //Much more checks
  1473.  
  1474.             //Unquote args
  1475.             if (!UnquoteArgs(args))
  1476.             {
  1477.                 Send( _T("501 Syntax error") );
  1478.                 break;
  1479.             }
  1480.  
  1481.             CStdString physicalFile, logicalFile;
  1482.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_APPEND, physicalFile, logicalFile);
  1483.             if (error & PERMISSION_DENIED)
  1484.             {
  1485.                 Send("550 Permission denied");
  1486.                 ResetTransferstatus();
  1487.             }
  1488.             else if (error & PERMISSION_INVALIDNAME)
  1489.             {
  1490.                 Send("550 Filename invalid.");
  1491.                 ResetTransferstatus();
  1492.             }
  1493.             else if (error)
  1494.             {
  1495.                 Send("550 Filename invalid");
  1496.                 ResetTransferstatus();
  1497.             }
  1498.             else
  1499.             {
  1500.                 _int64 size = 0;
  1501.                 if (!GetLength64(physicalFile, size))
  1502.                     size = 0;
  1503.  
  1504.                 m_transferstatus.rest = size;
  1505.  
  1506.                 if (!m_transferstatus.pasv)
  1507.                 {
  1508.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1509.                     transfersocket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1510.                     m_transferstatus.socket = transfersocket;
  1511.                     if (m_transferMode == mode_zlib)
  1512.                     {
  1513.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1514.                         {
  1515.                             Send("550 could not initialize zlib, please use MODE S instead");
  1516.                             ResetTransferstatus();
  1517.                             break;
  1518.                         }
  1519.                     }
  1520.  
  1521.                     if (!CreateTransferSocket(transfersocket))
  1522.                         break;
  1523.  
  1524.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1525.  
  1526.                     CStdString str;
  1527.                     str.Format("150 Opening data channel for file transfer, restarting at offset %I64d",size);
  1528.                     Send(str);
  1529.                 }
  1530.                 else
  1531.                 {
  1532.                     m_transferstatus.socket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1533.                     if (m_transferMode == mode_zlib)
  1534.                     {
  1535.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1536.                         {
  1537.                             Send("550 could not initialize zlib, please use MODE S instead");
  1538.                             ResetTransferstatus();
  1539.                             break;
  1540.                         }
  1541.                     }
  1542.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1543.                     m_transferstatus.socket->PasvTransfer();
  1544.                 }
  1545.                 GetSystemTime(&m_LastTransferTime);
  1546.             }
  1547.         }
  1548.         break;
  1549.     case COMMAND_NLST:
  1550.         if(m_transferstatus.pasv==-1)
  1551.         {
  1552.             Send("503 Bad sequence of commands.");
  1553.             break;
  1554.         }
  1555.         if (!m_transferstatus.pasv && (m_transferstatus.ip == "" || m_transferstatus.port == -1))
  1556.         {
  1557.             Send("503 Bad sequence of commands.");
  1558.             break;
  1559.         }
  1560.         if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1561.         {
  1562.             Send(_T("550 PROT P required"));
  1563.             break;
  1564.         }
  1565.         //Much more checks
  1566.         else
  1567.         {
  1568.             //Check args, currently only supported argument is the directory which will be listed.
  1569.             args.TrimLeft(" ");
  1570.             args.TrimRight(" ");
  1571.             if (args!="")
  1572.             {
  1573.                 BOOL bBreak=FALSE;
  1574.                 while (args[0]=='-') //No parameters supported
  1575.                 {
  1576.                     if (args.GetLength()<2)
  1577.                     { //Dash without param
  1578.                         Send("501 Syntax error");
  1579.                         bBreak = TRUE;
  1580.                         break;
  1581.                     }
  1582.  
  1583.                     int pos=args.Find(" ");
  1584.                     CStdString params;
  1585.                     if (pos!=-1)
  1586.                     {
  1587.                         params=args.Left(1);
  1588.                         params=params.Left(pos-1);
  1589.                         args=args.Mid(pos+1);
  1590.                         args.TrimLeft(" ");
  1591.                     }
  1592.                     else
  1593.                         args="";
  1594.                     while (params!="")
  1595.                     {
  1596.                         //Some parameters are not support
  1597.                         if (params[0]=='R')
  1598.                         {
  1599.                             Send("504 Command not implemented for that parameter");
  1600.                             bBreak = TRUE;
  1601.                             break;
  1602.                         }
  1603.                         //Ignore other parameters
  1604.                         params=params.Mid(1);
  1605.                     }
  1606.  
  1607.                     if (args=="")
  1608.                         break;
  1609.                 }
  1610.                 if (bBreak)
  1611.                     break;
  1612.                 if (args != "")
  1613.                 {
  1614.                     //Unquote args
  1615.                     if (!UnquoteArgs(args))
  1616.                     {
  1617.                         Send( _T("501 Syntax error") );
  1618.                         break;
  1619.                     }
  1620.                 }
  1621.             }
  1622.  
  1623.             t_dirlisting *pResult;
  1624.             CStdString physicalDir, logicalDir;
  1625.             int error = m_pOwner->m_pPermissions->GetShortDirectoryListing(m_status.user, m_CurrentServerDir, args, pResult, physicalDir, logicalDir);
  1626.             if (error & PERMISSION_DENIED)
  1627.             {
  1628.                 Send("550 Permission denied");
  1629.                 ResetTransferstatus();
  1630.             }
  1631.             else if (error & PERMISSION_INVALIDNAME)
  1632.             {
  1633.                 Send("550 Filename invalid.");
  1634.                 ResetTransferstatus();
  1635.             }
  1636.             else if (error)
  1637.             {
  1638.                 Send("550 Directory not found");
  1639.                 ResetTransferstatus();
  1640.             }
  1641.             else
  1642.             {
  1643.                 if (!m_transferstatus.pasv)
  1644.                 {
  1645.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1646.                     m_transferstatus.socket = transfersocket;
  1647.                     transfersocket->Init(pResult, TRANSFERMODE_NLST);
  1648.                     if (m_transferMode == mode_zlib)
  1649.                     {
  1650.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1651.                         {
  1652.                             Send("550 could not initialize zlib, please use MODE S instead");
  1653.                             ResetTransferstatus();
  1654.                             break;
  1655.                         }
  1656.                     }
  1657.  
  1658.                     if (!CreateTransferSocket(transfersocket))
  1659.                         break;
  1660.  
  1661.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir); // Use TRANSFERMODE_LIST instead of TRANSFERMODE_NLST.
  1662.                     Send("150 Opening data channel for directory list.");
  1663.                 }
  1664.                 else
  1665.                 {
  1666.                     m_transferstatus.socket->Init(pResult, TRANSFERMODE_NLST );
  1667.                     if (m_transferMode == mode_zlib)
  1668.                     {
  1669.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1670.                         {
  1671.                             Send("550 could not initialize zlib, please use MODE S instead");
  1672.                             ResetTransferstatus();
  1673.                             break;
  1674.                         }
  1675.                     }
  1676.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir); // Use TRANSFERMODE_LIST instead of TRANSFERMODE_NLST.
  1677.                     m_transferstatus.socket->PasvTransfer();
  1678.                 }
  1679.             }
  1680.         }
  1681.         break;
  1682.     case COMMAND_MDTM:
  1683.         {
  1684.             //Unquote args
  1685.             if (!UnquoteArgs(args))
  1686.             {
  1687.                 Send( _T("501 Syntax error") );
  1688.                 break;
  1689.             }
  1690.  
  1691.             CStdString physicalFile, logicalFile;
  1692.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_READ, physicalFile, logicalFile);
  1693.             if (error & PERMISSION_DENIED)
  1694.                 Send("550 Permission denied");
  1695.             else if (error & PERMISSION_INVALIDNAME)
  1696.                 Send("550 Filename invalid.");
  1697.             else if (error & 2)
  1698.                 Send("550 File not found");
  1699.             else
  1700.             {
  1701.                 CFileStatus64 status;
  1702.                 GetStatus64(physicalFile, status);
  1703.                 status.m_mtime;
  1704.                 CStdString str;
  1705.                 SYSTEMTIME time;
  1706.                 FileTimeToSystemTime(&status.m_mtime, &time);
  1707.                 str.Format("213 %04d%02d%02d%02d%02d%02d",
  1708.                             time.wYear,
  1709.                             time.wMonth,
  1710.                             time.wDay,
  1711.                             time.wHour,
  1712.                             time.wMinute,
  1713.                             time.wSecond);
  1714.                 Send(str);
  1715.             }
  1716.         }
  1717.         break;
  1718.     case COMMAND_EPSV:
  1719.         {
  1720.             if (m_transferstatus.socket)
  1721.             {
  1722.                 SendTransferinfoNotification();
  1723.                 delete m_transferstatus.socket;
  1724.             }
  1725.             m_transferstatus.socket = new CTransferSocket(this);
  1726.  
  1727.             unsigned int port = 0;
  1728.             unsigned int retries = 3;
  1729.             while (retries > 0) {
  1730.                 if (m_pOwner->m_pOptions->GetOptionVal(OPTION_USECUSTOMPASVPORT)) {
  1731.                     static UINT customPort = 0;
  1732.                     unsigned int minPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMINPORT);
  1733.                     unsigned int maxPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMAXPORT);
  1734.                     if (minPort > maxPort) {
  1735.                         unsigned int temp = minPort;
  1736.                         minPort = maxPort;
  1737.                         maxPort = temp;
  1738.                     }
  1739.                     if (customPort < minPort || customPort > maxPort) {
  1740.                         customPort = minPort;
  1741.                     }
  1742.                     port = customPort;
  1743.                     ++customPort;
  1744.                 }
  1745.                 if (m_transferstatus.socket->Create(port, SOCK_STREAM, FD_ACCEPT))
  1746.                 {
  1747.                     break;
  1748.                 }
  1749.                 --retries;
  1750.             }
  1751.             if (retries <= 0) {
  1752.                 delete m_transferstatus.socket;
  1753.                 m_transferstatus.socket=0;
  1754.                 Send("421 Can't create socket");
  1755.                 break;
  1756.             }
  1757.  
  1758.             if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  1759.                 m_transferstatus.socket->UseGSS(m_pGssLayer);
  1760.  
  1761.             if (m_pSslLayer && m_bProtP)
  1762.                 m_transferstatus.socket->UseSSL(new CAsyncSslSocketLayer(), m_pSslLayer->GetContext());
  1763.  
  1764.             if (!m_transferstatus.socket->Listen())
  1765.             {
  1766.                 delete m_transferstatus.socket;
  1767.                 m_transferstatus.socket=0;
  1768.                 Send("421 Can't create socket");
  1769.                 break;
  1770.             }
  1771.  
  1772.             //Now retrieve the port
  1773.             SOCKADDR_IN sockAddr;
  1774.             memset(&sockAddr, 0, sizeof(sockAddr));
  1775.  
  1776.             int nSockAddrLen = sizeof(sockAddr);
  1777.             BOOL bResult = m_transferstatus.socket->GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  1778.             if (bResult)
  1779.                 port = ntohs(sockAddr.sin_port);
  1780.             //Put the answer together
  1781.             CStdString str;
  1782.             str.Format("229 Entering Extended Passive Mode (|||%d|)", port);
  1783.             Send(str);
  1784.             m_transferstatus.pasv=1;
  1785.             break;
  1786.         }
  1787.     case COMMAND_EPRT:
  1788.         {
  1789.             if (m_transferstatus.socket)
  1790.             {
  1791.                 SendTransferinfoNotification();
  1792.                 delete m_transferstatus.socket;
  1793.                 m_transferstatus.socket=0;
  1794.             }
  1795.  
  1796.             if (args[0] != '|')
  1797.             {
  1798.                 Send("501 Syntax error");
  1799.                 break;
  1800.             }
  1801.             args = args.Mid(1);
  1802.  
  1803.             int pos = args.Find('|');
  1804.             if (pos < 1 || (pos>=(args.GetLength()-1)))
  1805.             {
  1806.                 Send("501 Syntax error");
  1807.                 break;
  1808.             }
  1809.             int protocol = _ttoi(args.Left(pos));
  1810.             if (protocol != 1)
  1811.             {
  1812.                 Send("522 Extended Port Failure - unknown network protocol");
  1813.                 break;
  1814.             }
  1815.             args = args.Mid(pos + 1);
  1816.  
  1817.             pos = args.Find('|');
  1818.             if (pos < 1 || (pos>=(args.GetLength()-1)))
  1819.             {
  1820.                 Send("501 Syntax error");
  1821.                 break;
  1822.             }
  1823.             CStdString ip = args.Left(pos);
  1824.             if (inet_addr(ip) == INADDR_NONE)
  1825.             {
  1826.                 Send("501 Syntax error");
  1827.                 break;
  1828.             }
  1829.             args = args.Mid(pos + 1);
  1830.  
  1831.             pos = args.Find('|');
  1832.             if (pos < 1)
  1833.             {
  1834.                 Send("501 Syntax error");
  1835.                 break;
  1836.             }
  1837.             int port = _ttoi(args.Left(pos));
  1838.             if (port<1 || port>65535)
  1839.             {
  1840.                 Send("501 Syntax error");
  1841.                 break;
  1842.             }
  1843.  
  1844.             m_transferstatus.port = port;
  1845.             m_transferstatus.ip = ip;
  1846.  
  1847.             m_transferstatus.pasv=0;
  1848.             Send("200 Port command successful");
  1849.             break;
  1850.         }
  1851.     case COMMAND_AUTH:
  1852.         {
  1853.             if (m_pGssLayer)
  1854.             {
  1855.                 Send("534 Authentication type already set to GSSAPI");
  1856.                 break;
  1857.             }
  1858.             else if (m_pSslLayer)
  1859.             {
  1860.                 Send("534 Authentication type already set to SSL");
  1861.                 break;
  1862.             }
  1863.             args.MakeUpper();
  1864.  
  1865.             if (args == _T("GSSAPI"))
  1866.             {
  1867.                 if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_USEGSS))
  1868.                 {
  1869.                     Send("502 GSSAPI authentication not implemented");
  1870.                     break;
  1871.                 }
  1872.  
  1873.                 m_pGssLayer = new CAsyncGssSocketLayer;
  1874.                 BOOL res = AddLayer(m_pGssLayer);
  1875.                 if (res)
  1876.                 {
  1877.                     res = m_pGssLayer->InitGSS(FALSE, (BOOL)m_pOwner->m_pOptions->GetOptionVal(OPTION_GSSPROMPTPASSWORD));
  1878.                     if (!res)
  1879.                         SendStatus("Unable to init GSS", 1);
  1880.                 }
  1881.                 if (!res)
  1882.                 {
  1883.                     RemoveAllLayers();
  1884.                     delete m_pGssLayer;
  1885.                     m_pGssLayer = NULL;
  1886.                     Send("431 Could not initialize GSSAPI libraries");
  1887.                     break;
  1888.                 }
  1889.  
  1890.                 Send("334 Using authentication type GSSAPI; ADAT must follow");
  1891.             }
  1892.             else if (args == _T("SSL") || args == _T("TLS"))
  1893.             {
  1894.                 if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_ENABLESSL) || ! m_pOwner->m_pOptions->GetOptionVal(OPTION_ALLOWEXPLICITSSL))
  1895.                 {
  1896.                     Send("502 SSL/TLS authentication not allowed");
  1897.                     break;
  1898.                 }
  1899.  
  1900.                 m_pSslLayer = new CAsyncSslSocketLayer;
  1901.                 BOOL res = AddLayer(m_pSslLayer);
  1902.  
  1903.                 if (res)
  1904.                 {
  1905.                     CString error;
  1906.                     int res = m_pSslLayer->SetCertKeyFile(m_pOwner->m_pOptions->GetOption(OPTION_SSLCERTFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYPASS));
  1907.                     if (res == SSL_FAILURE_LOADDLLS)
  1908.                         SendStatus("Failed to load SSL libraries", 1);
  1909.                     else if (res == SSL_FAILURE_INITSSL)
  1910.                         SendStatus("Failed to initialize SSL libraries", 1);
  1911.                     else if (res == SSL_FAILURE_VERIFYCERT)
  1912.                     {
  1913.                         if (error != "")
  1914.                             SendStatus(error, 1);
  1915.                         else
  1916.                             SendStatus("Failed to set certificate and private key", 1);
  1917.                     }
  1918.                     if (res)
  1919.                     {
  1920.                         RemoveAllLayers();
  1921.                         delete m_pSslLayer;
  1922.                         m_pSslLayer = NULL;
  1923.                         Send("431 Could not initialize SSL connection");
  1924.                         break;
  1925.                     }
  1926.                 }
  1927.  
  1928.                 if (res)
  1929.                 {
  1930.                     int code = m_pSslLayer->InitSSLConnection(false);
  1931.                     if (code == SSL_FAILURE_LOADDLLS)
  1932.                         SendStatus("Failed to load SSL libraries", 1);
  1933.                     else if (code == SSL_FAILURE_INITSSL)
  1934.                         SendStatus("Failed to initialize SSL library", 1);
  1935.  
  1936.                     res = (code == 0);
  1937.                 }
  1938.  
  1939.                 if (res)
  1940.                 {
  1941.                     CStdString reply = "234 Using authentication type " + args + "\r\n";
  1942.                     const int len = reply.GetLength();
  1943.                     SendStatus(reply, 3);
  1944.                     res = (m_pSslLayer->SendRaw(reply, len) == len);
  1945.                 }
  1946.  
  1947.                 if (!res)
  1948.                 {
  1949.                     RemoveAllLayers();
  1950.                     delete m_pSslLayer;
  1951.                     m_pSslLayer = NULL;
  1952.                     Send("431 Could not initialize SSL connection");
  1953.                     break;
  1954.                 }
  1955.             }
  1956.             else
  1957.             {
  1958.                 Send("504 Auth type not supported");
  1959.                 break;
  1960.             }
  1961.  
  1962.             break;
  1963.         }
  1964.     case COMMAND_ADAT:
  1965.         if (m_pGssLayer)
  1966.         {
  1967.             char sendme[4096];
  1968.  
  1969.             char command1[4096];
  1970.             char args1[4096];
  1971.  
  1972.             strcpy(command1, command);
  1973.             strupr(command1);
  1974.             strcpy(args1, args);
  1975.  
  1976.             m_pGssLayer->ProcessCommand(command1, args1, sendme);
  1977.             Send(sendme);
  1978.         }
  1979.         else
  1980.             Send("502 Command not implemented for this authentication type");
  1981.         break;
  1982.     case COMMAND_PBSZ:
  1983.         if (m_pGssLayer)
  1984.         {
  1985.             char sendme[4096];
  1986.  
  1987.             char command1[4096];
  1988.             char args1[4096];
  1989.  
  1990.             strcpy(command1, command);
  1991.             strupr(command1);
  1992.             strcpy(args1, args);
  1993.  
  1994.             m_pGssLayer->ProcessCommand(command1, args1, sendme);
  1995.             Send(sendme);
  1996.         }
  1997.         else if (m_pSslLayer)
  1998.             Send("200 PBSZ=0");
  1999.         else
  2000.             Send("502 Command not implemented for this authentication type");
  2001.         break;
  2002.     case COMMAND_PROT:
  2003.         if (m_pGssLayer)
  2004.         {
  2005.             char sendme[4096];
  2006.  
  2007.             char command1[4096];
  2008.             char args1[4096];
  2009.  
  2010.             strcpy(command1, command);
  2011.             strupr(command1);
  2012.             strcpy(args1, args);
  2013.  
  2014.             m_pGssLayer->ProcessCommand(command1, args1, sendme);
  2015.             Send(sendme);
  2016.         }
  2017.         else if (m_pSslLayer)
  2018.         {
  2019.             args.MakeUpper();
  2020.             if (args == "C")
  2021.             {
  2022.                 Send("200 Protection level set to C");
  2023.                 m_bProtP = false;
  2024.             }
  2025.             else if (args == "P")
  2026.             {
  2027.                 Send("200 Protection level set to P");
  2028.                 m_bProtP = true;
  2029.             }
  2030.             else if (args == "S" || args == "E")
  2031.                 Send("504 Protection level " + args + " not supported");
  2032.             else
  2033.                 Send("504 Protection level " + args + " not recognized");
  2034.         }
  2035.         else
  2036.             Send("502 Command not implemented for this authentication type");
  2037.         break;
  2038.     case COMMAND_FEAT:
  2039.         if (!Send("211-Features:"))
  2040.             break;
  2041.         if (!Send(" MDTM"))
  2042.             break;
  2043.         if (!Send(" REST STREAM"))
  2044.             break;
  2045.         if (!Send(" SIZE"))
  2046.             break;
  2047.         if (m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_USE))
  2048.         {
  2049.             if (!Send(" MODE Z"))
  2050.                 break;
  2051.         }
  2052.         if (!Send(" MLST type*;size*;modify*;"))
  2053.             break;
  2054.         if (!Send("211 End"))
  2055.             break;
  2056.         break;
  2057.     case COMMAND_MODE:
  2058.         if (args == "S" || args == "s")
  2059.         {
  2060.             m_transferMode = mode_stream;
  2061.             Send("200 MODE set to S.");
  2062.         }
  2063.         else if (args == "Z" || args == "z")
  2064.         {
  2065.             if (m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_USE) || m_transferMode == mode_zlib)
  2066.             {
  2067.                 if (m_transferMode == mode_zlib || CheckIpForZlib())
  2068.                 {
  2069.                     m_transferMode = mode_zlib;
  2070.                     Send("200 MODE set to Z.");
  2071.                 }
  2072.                 else
  2073.                     Send("504 MODE Z not allowed from your IP");
  2074.             }
  2075.             else
  2076.                 Send("504 MODE Z not enabled");
  2077.         }
  2078.         else if (args == "C" || args == "c" || args == "B" || args == "b")
  2079.             Send("502 Unimplemented MODE type");
  2080.         else
  2081.             Send("504 Unknown MODE type");
  2082.         break;
  2083.     case COMMAND_OPTS:
  2084.         args.MakeUpper();
  2085.         if (args.Left(13) == "MODE Z LEVEL ")
  2086.         {
  2087.             int level = atoi(args.Mid(13));
  2088.             if (m_zlibLevel == level || (level >= m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_LEVELMIN) && level <= m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_LEVELMAX)))
  2089.             {
  2090.                 m_zlibLevel = level;
  2091.                 CString str;
  2092.                 str.Format("200 MODE Z LEVEL set to %d", level);
  2093.                 Send(str);
  2094.             }
  2095.             else
  2096.                 Send("501 can't change MODE Z LEVEL do desired value");
  2097.         }
  2098.         else
  2099.             Send("501 Option not understood");
  2100.         break;
  2101.     case COMMAND_HELP:
  2102.         if (args == "")
  2103.         {
  2104.             Send("214-The following commands are recognized:");
  2105.             CString str;
  2106.             for (int i = 0; i < (sizeof(commands)/sizeof(t_command)); i++)
  2107.             {
  2108.                 CString cmd = commands[i].command;
  2109.                 while (cmd.GetLength() < 4)
  2110.                     cmd += " ";
  2111.                 str += "   " + cmd;
  2112.                 if (!((i + 1) % 8))
  2113.                 {
  2114.                     Send(str);
  2115.                     str = "";
  2116.                 }
  2117.             }
  2118.             if (str != "")
  2119.                 Send(str);
  2120.             Send("214 Have a nice day.");
  2121.         }
  2122.         else
  2123.         {
  2124.             args.MakeUpper();
  2125.  
  2126.             int i;
  2127.             for (i = 0; i < (sizeof(commands)/sizeof(t_command)); i++)
  2128.             {
  2129.                 if (args == commands[i].command)
  2130.                 {
  2131.                     CStdString str;
  2132.                     str.Format("214 Command %s is supported by FileZilla Server", args);
  2133.                     Send(str);
  2134.                     break;
  2135.                 }
  2136.             }
  2137.             if (i == (sizeof(commands)/sizeof(t_command)))
  2138.             {
  2139.                 CStdString str;
  2140.                 str.Format("502 Command %s is not recognized or supported by FileZilla Server", args);
  2141.                 Send(str);
  2142.             }
  2143.         }
  2144.         break;
  2145.     case COMMAND_ALLO:
  2146.         Send("202 No storage allocation neccessary.");
  2147.         break;
  2148.     case COMMAND_MLST:
  2149.         {
  2150.             CStdString fact;
  2151.             CStdString logicalName;
  2152.             int res = m_pOwner->m_pPermissions->GetFact(m_status.user, m_CurrentServerDir, args, fact, logicalName);
  2153.             if (res & PERMISSION_DENIED)
  2154.             {
  2155.                 Send("550 Permission denied.");
  2156.                 break;
  2157.             }
  2158.             else if (res & PERMISSION_INVALIDNAME)
  2159.             {
  2160.                 Send("550 Filename invalid.");
  2161.                 break;
  2162.             }
  2163.             else if (res)
  2164.             {
  2165.                 Send("550 File or directory not found.");
  2166.                 break;
  2167.             }
  2168.             CString str;
  2169.             str.Format("250-Listing %s", logicalName);
  2170.             if (!Send(str))
  2171.                 break;
  2172.             fact = " " + fact;
  2173.             if (!Send(fact))
  2174.                 break;
  2175.  
  2176.             Send("250 End");
  2177.         }
  2178.         break;
  2179.     case COMMAND_MLSD:
  2180.         if (m_transferstatus.pasv == -1)
  2181.         {
  2182.             Send("503 Bad sequence of commands.");
  2183.             break;
  2184.         }
  2185.         if (!m_transferstatus.pasv && (m_transferstatus.ip == "" || m_transferstatus.port == -1))
  2186.             Send("503 Bad sequence of commands.");
  2187.         //Much more checks
  2188.         else
  2189.         {
  2190.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  2191.             {
  2192.                 Send(_T("550 PROT P required"));
  2193.                 break;
  2194.             }
  2195.             if (args != "")
  2196.             {
  2197.                 //Unquote args
  2198.                 if (!UnquoteArgs(args))
  2199.                 {
  2200.                     Send(_T("501 Syntax error"));
  2201.                     break;
  2202.                 }
  2203.             }
  2204.  
  2205.             t_dirlisting *pResult;
  2206.             CStdString physicalDir, logicalDir;
  2207.             int error = m_pOwner->m_pPermissions->GetFacts(m_status.user, m_CurrentServerDir, args, pResult, physicalDir, logicalDir);
  2208.             if (error & PERMISSION_DENIED)
  2209.             {
  2210.                 Send("550 Permission denied");
  2211.                 ResetTransferstatus();
  2212.             }
  2213.             else if (error & PERMISSION_INVALIDNAME)
  2214.             {
  2215.                 Send("550 Filename invalid.");
  2216.                 ResetTransferstatus();
  2217.             }
  2218.             else if (error)
  2219.             {
  2220.                 Send("550 Directory not found");
  2221.                 ResetTransferstatus();
  2222.             }
  2223.             else
  2224.             {
  2225.                 if (!m_transferstatus.pasv)
  2226.                 {
  2227.                     if (m_transferstatus.socket)
  2228.                     {
  2229.                         SendTransferinfoNotification();
  2230.                         delete m_transferstatus.socket;
  2231.                     }
  2232.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  2233.                     m_transferstatus.socket = transfersocket;
  2234.                     transfersocket->Init(pResult, TRANSFERMODE_LIST);
  2235.                     if (m_transferMode == mode_zlib)
  2236.                     {
  2237.                         if (!transfersocket->InitZLib(m_zlibLevel))
  2238.                         {
  2239.                             Send("550 could not initialize zlib, please use MODE S instead");
  2240.                             ResetTransferstatus();
  2241.                             break;
  2242.                         }
  2243.                     }
  2244.  
  2245.                     if (!CreateTransferSocket(transfersocket))
  2246.                         break;
  2247.  
  2248.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir);
  2249.                     Send("150 Opening data channel for directory list.");
  2250.                 }
  2251.                 else
  2252.                 {
  2253.                     m_transferstatus.socket->Init(pResult, TRANSFERMODE_LIST );
  2254.                     if (m_transferMode == mode_zlib)
  2255.                     {
  2256.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  2257.                         {
  2258.                             Send("550 could not initialize zlib, please use MODE S instead");
  2259.                             ResetTransferstatus();
  2260.                             break;
  2261.                         }
  2262.                     }
  2263.  
  2264.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir);
  2265.                     m_transferstatus.socket->PasvTransfer();
  2266.                 }
  2267.             }
  2268.  
  2269.         }
  2270.         break;
  2271.     default:
  2272.         Send("502 Command not implemented.");
  2273.     }
  2274.  
  2275.     if (!m_RecvLineBuffer.empty())
  2276.         m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  2277.  
  2278.     return;
  2279. }
  2280.  
  2281. void CControlSocket::ProcessTransferMsg()
  2282. {
  2283.     if (!m_transferstatus.socket)
  2284.         return;
  2285.     int status = m_transferstatus.socket->GetStatus();
  2286.  
  2287.     GetSystemTime(&m_LastCmdTime);
  2288.     if (m_transferstatus.socket)
  2289.         if (m_transferstatus.socket->GetMode()==TRANSFERMODE_SEND || m_transferstatus.socket->GetMode()==TRANSFERMODE_RECEIVE)
  2290.             GetSystemTime(&m_LastTransferTime);
  2291.  
  2292.     if (status == 2 && m_transferstatus.pasv)
  2293.         m_pOwner->ExternalIPFailed();
  2294.  
  2295.     int mode = m_transferstatus.socket->GetMode();
  2296.     _int64 zlibBytesIn = 0;
  2297.     _int64 zlibBytesOut = 0;
  2298.     if (m_transferMode == mode_zlib)
  2299.         m_transferstatus.socket->GetZlibStats(zlibBytesIn, zlibBytesOut);
  2300.     ResetTransferstatus();
  2301.  
  2302.     if (!status)
  2303.     {
  2304.         if ((mode == TRANSFERMODE_LIST || mode == TRANSFERMODE_NLST || mode == TRANSFERMODE_SEND) && zlibBytesIn && zlibBytesOut)
  2305.         {
  2306.             if (zlibBytesIn >= zlibBytesOut)
  2307.             {
  2308.                 CString str;
  2309.                 _int64 percent = 10000 - (zlibBytesOut * 10000 / zlibBytesIn);
  2310.                 str.Format("226 Transfer OK, compression saved %I64d of %I64d bytes (%I64d.%02I64d%%)", zlibBytesIn - zlibBytesOut, zlibBytesIn, percent / 100, percent % 100);
  2311.                 Send(str);
  2312.             }
  2313.             else
  2314.             {
  2315.                 CString str;
  2316.                 _int64 percent = (zlibBytesOut * 10000 / zlibBytesIn) - 10000;
  2317.                 str.Format("226 Transfer OK, unfortunately compression did increase the transfer size by %I64d bytes to %I64d bytes (%I64d.%02I64d%%)", zlibBytesOut - zlibBytesIn, zlibBytesOut, percent / 100, percent % 100);
  2318.                 Send(str);
  2319.             }
  2320.         }
  2321.         else if (mode == TRANSFERMODE_RECEIVE && zlibBytesIn && zlibBytesOut)
  2322.         {
  2323.             if (zlibBytesOut >= zlibBytesIn)
  2324.             {
  2325.                 CString str;
  2326.                 _int64 percent = 10000 - (zlibBytesIn * 10000 / zlibBytesOut);
  2327.                 str.Format("226 Transfer OK, compression saved %I64d of %I64d bytes (%I64d.%02I64d%%)", zlibBytesOut - zlibBytesIn, zlibBytesOut, percent / 100, percent % 100);
  2328.                 Send(str);
  2329.             }
  2330.             else
  2331.             {
  2332.                 CString str;
  2333.                 _int64 percent = (zlibBytesIn * 10000 / zlibBytesOut) - 10000;
  2334.                 str.Format("226 Transfer OK, unfortunately compression did increase the transfer size by %I64d bytes to %I64d bytes (%I64d.%02I64d%%)", zlibBytesIn - zlibBytesOut, zlibBytesIn, percent / 100, percent % 100);
  2335.                 Send(str);
  2336.             }
  2337.         }
  2338.         else
  2339.             Send("226 Transfer OK");
  2340.     }
  2341.     else if (status==1)
  2342.         Send("426 Connection closed; transfer aborted.");
  2343.     else if (status==2)
  2344.         Send("425 Can't open data connection.");
  2345.     else if (status==3)
  2346.         Send("450 can't access file.");
  2347.     else if (status==4)
  2348.     {
  2349.         Send("426 Connection timed out, aborting transfer");
  2350.         ForceClose(1);
  2351.         return;
  2352.     }
  2353.     else if (status==5)
  2354.         Send("425 Can't open data connection");
  2355.     else if (status==6)
  2356.         Send("450 zlib error");
  2357.     if (status>=0 && m_bWaitGoOffline)
  2358.         ForceClose(0);
  2359.     else if (m_bQuitCommand)
  2360.     {
  2361.         Send("221 Goodbye");
  2362.         if (CanQuit())
  2363.             ForceClose(5);
  2364.     }
  2365. }
  2366.  
  2367. CTransferSocket* CControlSocket::GetTransferSocket()
  2368. {
  2369.     return m_transferstatus.socket;
  2370. }
  2371.  
  2372. void CControlSocket::ForceClose(int nReason)
  2373. {
  2374.     if (m_transferstatus.socket)
  2375.     {
  2376.         // Don't call SendTransferInfoNotification, since connection
  2377.         // does get removed real soon.
  2378.         m_transferstatus.socket->Close();
  2379.         delete m_transferstatus.socket;
  2380.         m_transferstatus.socket=0;
  2381.     }
  2382.     if (!nReason)
  2383.         Send("421 Server is going offline");
  2384.     else if (nReason==1)
  2385.         Send("421 Connection timed out.");
  2386.     else if (nReason==2)
  2387.         Send("421 No-transfer-time exceeded. Closing control connection.");
  2388.     else if (nReason==3)
  2389.         Send("421 Login time exceeded. Closing control connection.");
  2390.     else if (nReason==4)
  2391.         Send("421 Kicked by Administrator");
  2392.     else if (nReason==5)
  2393.     {
  2394.         // 221 Goodbye
  2395.     }
  2396.     SendStatus("disconnected.",0);
  2397.     Close();
  2398.     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG,FTM_DELSOCKET,m_userid);
  2399.  
  2400. }
  2401.  
  2402. void CControlSocket::IncUserCount(const CStdString &user)
  2403. {
  2404.     int curcount=GetUserCount(user)+1;
  2405.     EnterCritSection(m_Sync);
  2406.     m_UserCount[user]=curcount;
  2407.     LeaveCritSection(m_Sync);
  2408. }
  2409.  
  2410. void CControlSocket::DecUserCount(const CStdString &user)
  2411. {
  2412.     int curcount=GetUserCount(user)-1;
  2413.     if (curcount<0)
  2414.         return;
  2415.     EnterCritSection(m_Sync);
  2416.     m_UserCount[user]=curcount;
  2417.     LeaveCritSection(m_Sync);
  2418. }
  2419.  
  2420. int CControlSocket::GetUserCount(const CStdString &user)
  2421. {
  2422.     EnterCritSection(m_Sync);
  2423.     int count=0;
  2424.     std::map<CStdString, int>::iterator iter = m_UserCount.find(user);
  2425.     if (iter!=m_UserCount.end())
  2426.         count = iter->second;
  2427.     LeaveCritSection(m_Sync);
  2428.     return count;
  2429. }
  2430.  
  2431. void CControlSocket::CheckForTimeout()
  2432. {
  2433.     if (m_antiHammeringWaitTime)
  2434.     {
  2435.         m_antiHammeringWaitTime -= 1000;
  2436.         if (m_antiHammeringWaitTime <= 0)
  2437.         {
  2438.             m_antiHammeringWaitTime = 0;
  2439.             TriggerEvent(FD_FORCEREAD);
  2440.         }
  2441.     }
  2442.     if (m_status.hammerValue > 0)
  2443.         m_status.hammerValue--;
  2444.  
  2445.     if (m_transferstatus.socket)
  2446.     {
  2447.         if (m_transferstatus.socket->CheckForTimeout())
  2448.             return;
  2449.     }
  2450.     _int64 timeout = m_pOwner->m_pOptions->GetOptionVal(OPTION_TIMEOUT);
  2451.     if (!timeout)
  2452.         return;
  2453.     SYSTEMTIME sCurrentTime;
  2454.     GetSystemTime(&sCurrentTime);
  2455.     FILETIME fCurrentTime;
  2456.     SystemTimeToFileTime(&sCurrentTime, &fCurrentTime);
  2457.     FILETIME fLastTime;
  2458.     SystemTimeToFileTime(&m_LastCmdTime, &fLastTime);
  2459.     _int64 elapsed = ((_int64)(fCurrentTime.dwHighDateTime - fLastTime.dwHighDateTime) << 32) + fCurrentTime.dwLowDateTime - fLastTime.dwLowDateTime;
  2460.     if (elapsed > (timeout*10000000))
  2461.     {
  2462.         ForceClose(1);
  2463.         return;
  2464.     }
  2465.     if (m_status.loggedon)
  2466.     { //Transfer timeout
  2467.         _int64 nNoTransferTimeout=m_pOwner->m_pOptions->GetOptionVal(OPTION_NOTRANSFERTIMEOUT);
  2468.         if (!nNoTransferTimeout)
  2469.             return;
  2470.         SystemTimeToFileTime(&m_LastTransferTime, &fLastTime);
  2471.         elapsed = ((_int64)(fCurrentTime.dwHighDateTime - fLastTime.dwHighDateTime) << 32) + fCurrentTime.dwLowDateTime - fLastTime.dwLowDateTime;
  2472.         if (elapsed>(nNoTransferTimeout*10000000))
  2473.         {
  2474.             ForceClose(2);
  2475.             return;
  2476.         }
  2477.     }
  2478.     else
  2479.     { //Login timeout
  2480.         _int64 nLoginTimeout=m_pOwner->m_pOptions->GetOptionVal(OPTION_LOGINTIMEOUT);
  2481.         if (!nLoginTimeout)
  2482.             return;
  2483.         SystemTimeToFileTime(&m_LoginTime, &fLastTime);
  2484.         elapsed = ((_int64)(fCurrentTime.dwHighDateTime - fLastTime.dwHighDateTime) << 32) + fCurrentTime.dwLowDateTime - fLastTime.dwLowDateTime;
  2485.         if (elapsed>(nLoginTimeout*10000000))
  2486.         {
  2487.             ForceClose(3);
  2488.             return;
  2489.         }
  2490.     }
  2491. }
  2492.  
  2493. void CControlSocket::WaitGoOffline(bool wait /*=true*/)
  2494. {
  2495.     if (!wait)
  2496.     {
  2497.         m_bWaitGoOffline = FALSE;
  2498.         return;
  2499.     }
  2500.  
  2501.     if (m_transferstatus.socket)
  2502.     {
  2503.         if (!m_transferstatus.socket->Started())
  2504.             ForceClose(0);
  2505.         else
  2506.             m_bWaitGoOffline=TRUE;
  2507.     }
  2508.     else
  2509.         ForceClose(0);
  2510.  
  2511. }
  2512.  
  2513. void CControlSocket::ResetTransferstatus()
  2514. {
  2515.     if (m_transferstatus.socket)
  2516.     {
  2517.         SendTransferinfoNotification();
  2518.         delete m_transferstatus.socket;
  2519.     }
  2520.     m_transferstatus.socket = 0;
  2521.     m_transferstatus.ip = "";
  2522.     m_transferstatus.port = -1;
  2523.     m_transferstatus.pasv = -1;
  2524.     m_transferstatus.rest = 0;
  2525. }
  2526.  
  2527. BOOL CControlSocket::UnquoteArgs(CStdString &args)
  2528. {
  2529.     args.TrimLeft( _T(" ") );
  2530.     args.TrimRight( _T(" ") );
  2531.     int pos1=args.Find('"');
  2532.     int pos2=args.ReverseFind('"');
  2533.     if (pos1==-1 && pos2==-1)
  2534.         return TRUE;
  2535.     if (pos1 || pos2!=(args.GetLength()-1) || pos1>=(pos2-1))
  2536.         return FALSE;
  2537.     args=args.Mid(1, args.GetLength()-2);
  2538.     if (args.Find('"')!=-1 || args.Left(1)==" " || args.Right(1)==" ")
  2539.         return FALSE;
  2540.     return TRUE;
  2541. }
  2542.  
  2543. void CControlSocket::OnSend(int nErrorCode)
  2544. {
  2545.     if (m_nSendBufferLen && m_pSendBuffer)
  2546.     {
  2547.         int nLimit = GetSpeedLimit(download);
  2548.         if (!nLimit)
  2549.             return;
  2550.         int numsend = nLimit;
  2551.         if (nLimit == -1 || nLimit > m_nSendBufferLen)
  2552.             numsend = m_nSendBufferLen;
  2553.  
  2554.  
  2555.         int numsent = CAsyncSocketEx::Send(m_pSendBuffer, numsend);
  2556.  
  2557.         if (numsent==SOCKET_ERROR && GetLastError() == WSAEWOULDBLOCK)
  2558.             return;
  2559.         if (!numsent || numsent == SOCKET_ERROR)
  2560.         {
  2561.             Close();
  2562.             SendStatus("could not send reply, disconnected.",0);
  2563.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  2564.  
  2565.             delete [] m_pSendBuffer;
  2566.             m_pSendBuffer = NULL;
  2567.             m_nSendBufferLen = 0;
  2568.  
  2569.             return;
  2570.         }
  2571.  
  2572.         if (nLimit != -1)
  2573.             m_SlQuotas[download].nTransferred += numsent;
  2574.  
  2575.         if (numsent == m_nSendBufferLen)
  2576.         {
  2577.             delete [] m_pSendBuffer;
  2578.             m_pSendBuffer = NULL;
  2579.             m_nSendBufferLen = 0;
  2580.         }
  2581.         else
  2582.         {
  2583.             char *tmp = m_pSendBuffer;
  2584.             m_pSendBuffer = new char[m_nSendBufferLen-numsent];
  2585.             memcpy(m_pSendBuffer, tmp+numsent, m_nSendBufferLen-numsent);
  2586.             delete [] tmp;
  2587.             m_nSendBufferLen -= numsent;
  2588.             TriggerEvent(FD_WRITE);
  2589.         }
  2590.     }
  2591. }
  2592.  
  2593. BOOL CControlSocket::DoUserLogin(const char* password, bool skipPass /*=false*/)
  2594. {
  2595.     CUser user;
  2596.     if (!m_pOwner->m_pPermissions->CheckUserLogin(m_status.user, password, user, skipPass))
  2597.     {
  2598.         AntiHammerIncrease(2);
  2599.         SOCKADDR_IN sockAddr;
  2600.         memset(&sockAddr, 0, sizeof(sockAddr));
  2601.         int nSockAddrLen = sizeof(sockAddr);
  2602.         BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  2603.         if (bResult)
  2604.             m_pOwner->AntiHammerIncrease(sockAddr.sin_addr.s_addr);
  2605.  
  2606.         Send("530 Login or password incorrect!");
  2607.         return FALSE;
  2608.     }
  2609.  
  2610.     if (!user.IsEnabled())
  2611.     {
  2612.         Send("530 Not logged in, user account has been disabled");
  2613.         ForceClose(-1);
  2614.         return FALSE;
  2615.     }
  2616.     if (!user.BypassUserLimit())
  2617.     {
  2618.         int nMaxUsers = (int)m_pOwner->m_pOptions->GetOptionVal(OPTION_MAXUSERS);
  2619.         if (m_pOwner->GetGlobalNumConnections()>nMaxUsers&&nMaxUsers)
  2620.         {
  2621.             SendStatus("Refusing connection. Reason: Max. connection count reached.",1);
  2622.             Send("421 Too many users are connected, please try again later.");
  2623.             ForceClose(-1);
  2624.             return FALSE;
  2625.         }
  2626.     }
  2627.     if (user.GetUserLimit() && GetUserCount(m_status.user)>=user.GetUserLimit())
  2628.     {
  2629.             CStdString str;
  2630.             str.Format("Refusing connection. Reason: Max. connection count reached for the user \"%s\".", m_status.user);
  2631.             SendStatus(str,1);
  2632.             Send("421 Too many users logged in for this account. Try again later.");
  2633.             ForceClose(-1);
  2634.             return FALSE;
  2635.     }
  2636.  
  2637.     CStdString ip;
  2638.     unsigned int nPort;
  2639.  
  2640.     SOCKADDR_IN sockAddr;
  2641.     memset(&sockAddr, 0, sizeof(sockAddr));
  2642.     int nSockAddrLen = sizeof(sockAddr);
  2643.     BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  2644.     if (bResult)
  2645.     {
  2646.         if (!user.AccessAllowed(sockAddr))
  2647.         {
  2648.             Send("421 This user is not allowed to connect from this IP");
  2649.             ForceClose(-1);
  2650.             return FALSE;
  2651.         }
  2652.         nPort = ntohs(sockAddr.sin_port);
  2653.         ip = inet_ntoa(sockAddr.sin_addr);
  2654.     }
  2655.  
  2656.     int count = m_pOwner->GetIpCount(ip);
  2657.     if (user.GetIpLimit() && count >= user.GetIpLimit())
  2658.     {
  2659.         CStdString str;
  2660.         if (count==1)
  2661.             str.Format("Refusing connection. Reason: No more connections allowed from this IP. (%s already connected once)",ip);
  2662.         else
  2663.             str.Format("Refusing connection. Reason: No more connections allowed from this IP. (%s already connected %d times)",ip,count);
  2664.         SendStatus(str, 1);
  2665.         Send("421 Refusing connection. No more connections allowed from your IP.");
  2666.         ForceClose(-1);
  2667.         return FALSE;
  2668.     }
  2669.  
  2670.     m_CurrentServerDir = m_pOwner->m_pPermissions->GetHomeDir(m_status.user);
  2671.     if (m_CurrentServerDir == "")
  2672.     {
  2673.         Send("550 Could not get home dir!");
  2674.         ForceClose(-1);
  2675.         return FALSE;
  2676.     }
  2677.  
  2678.     m_status.ip = ip;
  2679.  
  2680.     count = GetUserCount(user.user);
  2681.     if (user.GetUserLimit() && count >= user.GetUserLimit())
  2682.     {
  2683.         CStdString str;
  2684.         str.Format("Refusing connection. Reason: Maximum connection count (%d) reached for this user", user.GetUserLimit());
  2685.         SendStatus(str, 1);
  2686.         str.Format("421 Refusing connection. Maximum connection count reached for the user '%s'", user.user);
  2687.         Send(str);
  2688.         ForceClose(-1);
  2689.         return FALSE;
  2690.     }
  2691.  
  2692.     m_pOwner->IncIpCount(ip);
  2693.     IncUserCount(m_status.user);
  2694.     m_status.loggedon = TRUE;
  2695.  
  2696.     GetSystemTime(&m_LastTransferTime);
  2697.  
  2698.     m_pOwner->m_pPermissions->AutoCreateDirs(m_status.user);
  2699.  
  2700.     t_connectiondata_changeuser *conndata = new t_connectiondata_changeuser;
  2701.     t_connop *op = new t_connop;
  2702.     op->data = conndata;
  2703.     op->op = USERCONTROL_CONNOP_CHANGEUSER;
  2704.     op->userid = m_userid;
  2705.     conndata->user = m_status.user;
  2706.  
  2707.     m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  2708.  
  2709.     return TRUE;
  2710. }
  2711.  
  2712. void CControlSocket::Continue()
  2713. {
  2714.     if (m_SlQuotas[download].bContinue)
  2715.     {
  2716.         TriggerEvent(FD_WRITE);
  2717.         if (m_transferstatus.socket && m_transferstatus.socket->Started())
  2718.             m_transferstatus.socket->TriggerEvent(FD_WRITE);
  2719.         m_SlQuotas[download].bContinue = false;
  2720.     }
  2721.  
  2722.     if (m_SlQuotas[upload].bContinue)
  2723.     {
  2724.         TriggerEvent(FD_READ);
  2725.         if (m_transferstatus.socket && m_transferstatus.socket->Started())
  2726.             m_transferstatus.socket->TriggerEvent(FD_READ);
  2727.         m_SlQuotas[upload].bContinue = false;
  2728.     }
  2729. }
  2730.  
  2731. int CControlSocket::GetSpeedLimit(sltype mode)
  2732. {
  2733.     CUser user;
  2734.     int nLimit = -1;
  2735.     if (m_status.loggedon && m_pOwner->m_pPermissions->GetUser(m_status.user, user))
  2736.     {
  2737.         nLimit = user.GetCurrentSpeedLimit(mode);
  2738.     }
  2739.     if (nLimit > 0)
  2740.     {
  2741.         nLimit *= 100;
  2742.         if (m_SlQuotas[mode].nTransferred >= nLimit)
  2743.         {
  2744.             m_SlQuotas[mode].bContinue = TRUE;
  2745.             return 0;
  2746.         }
  2747.         else
  2748.             nLimit -= m_SlQuotas[mode].nTransferred;
  2749.     }
  2750.     else
  2751.         nLimit = -1;
  2752.     if (user.BypassServerSpeedLimit(mode))
  2753.         m_SlQuotas[mode].bBypassed = TRUE;
  2754.     else if (m_SlQuotas[mode].nBytesAllowedToTransfer != -1)
  2755.     {
  2756.         if (nLimit == -1 || nLimit > (m_SlQuotas[mode].nBytesAllowedToTransfer - m_SlQuotas[mode].nTransferred))
  2757.             nLimit = m_SlQuotas[mode].nBytesAllowedToTransfer - m_SlQuotas[mode].nTransferred;
  2758.     }
  2759.  
  2760.     if (!nLimit)
  2761.         m_SlQuotas[mode].bContinue = TRUE;
  2762.  
  2763.     return nLimit;
  2764. }
  2765.  
  2766. BOOL CControlSocket::CreateTransferSocket(CTransferSocket *pTransferSocket)
  2767. {
  2768.     /* Create socket
  2769.      * First try control connection port - 1, if that fails try
  2770.      * control connection port + 1. If that fails as well, let
  2771.      * the OS decide.
  2772.      */
  2773.     BOOL bCreated = FALSE;
  2774.     // Get local port
  2775.     SOCKADDR_IN sockAddr;
  2776.     int nSockAddrLen = sizeof(sockAddr);
  2777.     memset(&sockAddr, 0, sizeof(sockAddr));
  2778.  
  2779.     // Fix: Formerly, the data connection would always be opened using the server's default (primary) IP.
  2780.     // This would cause Windows Firewall to freak out if control connection was opened on a secondary IP.
  2781.     // When using Active FTP behind Windows Firewall, no connection could be made. This fix ensures the data
  2782.     // socket is on the same IP as the control socket.
  2783.     CStdString controlIP;
  2784.     BOOL bResult = this->GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  2785.     if (bResult)
  2786.         controlIP = inet_ntoa(sockAddr.sin_addr);
  2787.  
  2788.     if (GetSockName((SOCKADDR *)&sockAddr, &nSockAddrLen))
  2789.     {
  2790.         int nPort = ntohs(sockAddr.sin_port);
  2791.         // Try create control conn. port - 1
  2792.         if (nPort > 1)
  2793.             if (pTransferSocket->Create(nPort - 1, SOCK_STREAM, FD_CONNECT, controlIP))
  2794.                 bCreated = TRUE;
  2795.         // Try create control conn. port + 1 if necessary
  2796.         if (!bCreated && nPort < 65535)
  2797.             if (pTransferSocket->Create(nPort + 1, SOCK_STREAM, FD_CONNECT, controlIP))
  2798.                 bCreated = TRUE;
  2799.     }
  2800.     if (!bCreated)
  2801.     {
  2802.         // Let the OS find a valid port
  2803.         if (!pTransferSocket->Create(0, SOCK_STREAM, FD_CONNECT, controlIP))
  2804.         {
  2805.             // Give up
  2806.             Send("421 Can't create socket");
  2807.             ResetTransferstatus();
  2808.             return FALSE;
  2809.         }
  2810.     }
  2811.     if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  2812.         m_transferstatus.socket->UseGSS(m_pGssLayer);
  2813.  
  2814.     if (pTransferSocket->Connect(m_transferstatus.ip,m_transferstatus.port)==0)
  2815.     {
  2816.         if (GetLastError() != WSAEWOULDBLOCK)
  2817.         {
  2818.             Send("425 Can't open data connection");
  2819.             ResetTransferstatus();
  2820.             return FALSE;
  2821.         }
  2822.     }
  2823.  
  2824.     if (m_pSslLayer && m_bProtP)
  2825.         pTransferSocket->UseSSL(new CAsyncSslSocketLayer(), m_pSslLayer->GetContext());
  2826.  
  2827.     return TRUE;
  2828. }
  2829.  
  2830. bool CControlSocket::CheckIpForZlib()
  2831. {
  2832.     SOCKADDR_IN sockAddr;
  2833.     memset(&sockAddr, 0, sizeof(sockAddr));
  2834.     int nSockAddrLen = sizeof(sockAddr);
  2835.     BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  2836.     if (!bResult)
  2837.         return true;
  2838.  
  2839.     unsigned int ip = htonl(sockAddr.sin_addr.s_addr);
  2840.     const char *pIp = inet_ntoa(sockAddr.sin_addr);
  2841.  
  2842.     if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_ALLOWLOCAL))
  2843.     {
  2844.         if (ip >= 0x0A000000 && ip <= 0x0AFFFFFF)
  2845.             return false;
  2846.         if (ip >= 0xAC100000 && ip <= 0xAC1FFFFF)
  2847.             return false;
  2848.         if (ip >= 0xC0A80000 && ip <= 0xC0A80000)
  2849.             return false;
  2850.         if (ip == 0x7F000001)
  2851.             return false;
  2852.     }
  2853.  
  2854.     CStdString ips = m_pOwner->m_pOptions->GetOption(OPTION_MODEZ_DISALLOWED_IPS);
  2855.     ips += " ";
  2856.  
  2857.     int pos = ips.Find(' ');
  2858.     while (pos != -1)
  2859.     {
  2860.         CStdString blockedIP = ips.Left(pos);
  2861.         ips = ips.Mid(pos + 1);
  2862.         pos = ips.Find(' ');
  2863.  
  2864.         if (MatchesFilter(blockedIP, ip, pIp))
  2865.             return false;
  2866.     }
  2867.  
  2868.     return true;
  2869. }
  2870.  
  2871. void CControlSocket::AntiHammerIncrease(int amount /*=1*/)
  2872. {
  2873.     if (m_status.hammerValue < 8000)
  2874.         m_status.hammerValue += amount * 200;
  2875.  
  2876.     if (m_status.hammerValue > 2000)
  2877.         m_antiHammeringWaitTime += 1000 * (int)pow(1.3, (m_status.hammerValue / 400) - 5);
  2878. }
  2879.  
  2880. void CControlSocket::SendTransferinfoNotification(const char transfermode, const CStdString& physicalFile, const CStdString& logicalFile, __int64 startOffset, __int64 totalSize)
  2881. {
  2882.     t_connop *op = new t_connop;
  2883.     op->op = USERCONTROL_CONNOP_TRANSFERINIT;
  2884.     op->userid = m_userid;
  2885.  
  2886.     t_connectiondata_transferinfo *conndata = new t_connectiondata_transferinfo;
  2887.     conndata->transferMode = transfermode;
  2888.     conndata->physicalFile = physicalFile;
  2889.     conndata->logicalFile = logicalFile;
  2890.     conndata->startOffset = startOffset;
  2891.     conndata->totalSize = totalSize;
  2892.     op->data = conndata;
  2893.  
  2894.     m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  2895. }
  2896.  
  2897. int CControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
  2898. {
  2899.     for (std::list<t_callbackMsg>::iterator iter = callbacks.begin(); iter != callbacks.end(); iter++)
  2900.     {
  2901.         if (m_pSslLayer && iter->pLayer == m_pSslLayer)
  2902.         {
  2903.             if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC && iter->nParam1 == SSL_INFO_ESTABLISHED)
  2904.                 SendStatus("SSL connection established", 0);
  2905.             else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC && iter->nParam1 == SSL_INFO && iter->nParam2 == SSL_INFO_SHUTDOWNCOMPLETE)
  2906.             {
  2907.                 if (!m_bQuitCommand)
  2908.                     continue;
  2909.  
  2910.                 do
  2911.                 {
  2912.                     delete [] iter->str;
  2913.                     iter++;
  2914.                 } while (iter != callbacks.end());
  2915.  
  2916.                 ForceClose(5);
  2917.  
  2918.                 return 0;
  2919.             }
  2920.         }
  2921.         else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC && iter->nParam1 == SSL_VERBOSE_WARNING)
  2922.         {
  2923.             if (iter->str)
  2924.             {
  2925.                 CStdString str = "SSL warning: ";
  2926.                 str += iter->str;
  2927.  
  2928.                 SendStatus(str, 1);
  2929.             }
  2930.         }
  2931.         delete [] iter->str;
  2932.     }
  2933.     return 0;//CAsyncSocketEx::OnLayerCallback(pLayer, nType, nParam1, nParam2);
  2934. }
  2935.  
  2936. bool CControlSocket::InitImplicitSsl()
  2937. {
  2938.     m_pSslLayer = new CAsyncSslSocketLayer;
  2939.     int res = AddLayer(m_pSslLayer) ? 1 : 0;
  2940.     if (!res)
  2941.     {
  2942.         delete m_pSslLayer;
  2943.         m_pSslLayer = 0;
  2944.         return false;
  2945.     }
  2946.  
  2947.     CString error;
  2948.     res = m_pSslLayer->SetCertKeyFile(m_pOwner->m_pOptions->GetOption(OPTION_SSLCERTFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYPASS));
  2949.     if (res == SSL_FAILURE_LOADDLLS)
  2950.         SendStatus("Failed to load SSL libraries", 1);
  2951.     else if (res == SSL_FAILURE_INITSSL)
  2952.         SendStatus("Failed to initialize SSL libraries", 1);
  2953.     else if (res == SSL_FAILURE_VERIFYCERT)
  2954.     {
  2955.         if (error != "")
  2956.             SendStatus(error, 1);
  2957.         else
  2958.             SendStatus("Failed to set certificate and private key", 1);
  2959.     }
  2960.     if (res)
  2961.     {
  2962.         RemoveAllLayers();
  2963.         delete m_pSslLayer;
  2964.         m_pSslLayer = NULL;
  2965.         Send("431 Could not initialize SSL connection", 1);
  2966.         return false;
  2967.     }
  2968.  
  2969.     int code = m_pSslLayer->InitSSLConnection(false);
  2970.     if (code == SSL_FAILURE_LOADDLLS)
  2971.         SendStatus("Failed to load SSL libraries", 1);
  2972.     else if (code == SSL_FAILURE_INITSSL)
  2973.         SendStatus("Failed to initialize SSL library", 1);
  2974.  
  2975.     if (!code)
  2976.         return true;
  2977.  
  2978.     RemoveAllLayers();
  2979.     delete m_pSslLayer;
  2980.     m_pSslLayer = NULL;
  2981.     Send("431 Could not initialize SSL connection");
  2982.  
  2983.     //Close socket
  2984.     Close();
  2985.     SendStatus("disconnected.", 0);
  2986.     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  2987.  
  2988.     return false;
  2989. }
  2990.  
  2991. bool CControlSocket::CanQuit()
  2992. {
  2993.     if (m_pSslLayer)
  2994.         return false;
  2995.     return true;
  2996. }
  2997.