home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 217 / DPCS0306DVD.ISO / Toolkit / Internet / FileZilla / Server / FileZilla_Server-0.9.11.exe / source / Server.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-08-21  |  37.4 KB  |  1,240 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. // Server.cpp: Implementierung der Klasse CServer.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22.  
  23. #include "stdafx.h"
  24. #include "Server.h"
  25. #include "Options.h"
  26. #include "ServerThread.h"
  27. #include "ListenSocket.h"
  28. #include "AdminListenSocket.h"
  29. #include "AdminInterface.h"
  30. #include "AdminSocket.h"
  31. #include "Permissions.h"
  32. #include "FileLogger.h"
  33. #include "version.h"
  34. #include "defs.h"
  35.  
  36. #ifndef MB_SERVICE_NOTIFICATION
  37. #define MB_SERVICE_NOTIFICATION          0x00040000L
  38. #endif
  39.  
  40. //////////////////////////////////////////////////////////////////////
  41. // Konstruktion/Destruktion
  42. //////////////////////////////////////////////////////////////////////
  43.  
  44. CServer::CServer()
  45. {
  46.     m_hWnd=0;
  47.     m_pOptions = NULL;
  48.     m_pAdminInterface = new CAdminInterface(this);
  49.     m_nServerState = 0;
  50.     m_bQuit = FALSE;
  51.  
  52.     m_nSendCount = m_nRecvCount = 0;
  53.     m_nTimerID = 0;
  54.  
  55.     // Since this thread has to handle notifications, increase it's priority
  56.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  57. }
  58.  
  59. CServer::~CServer()
  60. {
  61.     for (std::list<CListenSocket*>::iterator iter = m_ListenSocketList.begin(); iter != m_ListenSocketList.end(); iter++)
  62.         delete *iter;
  63.     m_ListenSocketList.clear();
  64.     
  65.     for (std::list<CAdminListenSocket*>::iterator adminIter = m_AdminListenSocketList.begin(); adminIter != m_AdminListenSocketList.end(); adminIter++)
  66.         delete *adminIter;
  67.     m_AdminListenSocketList.clear();
  68.  
  69.     delete m_pAdminInterface;
  70.  
  71.     delete m_pFileLogger;
  72.     delete m_pOptions;
  73.  
  74.     //Destroy window
  75.     if (m_hWnd)
  76.     {
  77.         hMainWnd = 0;
  78.         DestroyWindow(m_hWnd);
  79.         m_hWnd=0;
  80.     }
  81. }
  82.  
  83. bool CServer::Create()
  84. {
  85.     //Create window
  86.     WNDCLASSEX wndclass; 
  87.     wndclass.cbSize=sizeof wndclass; 
  88.     wndclass.style=0; 
  89.     wndclass.lpfnWndProc=WindowProc; 
  90.     wndclass.cbClsExtra=0; 
  91.     wndclass.cbWndExtra=0; 
  92.     wndclass.hInstance=GetModuleHandle(0); 
  93.     wndclass.hIcon=0; 
  94.     wndclass.hCursor=0; 
  95.     wndclass.hbrBackground=0; 
  96.     wndclass.lpszMenuName=0; 
  97.     wndclass.lpszClassName=_T("FileZilla Server Helper Window"); 
  98.     wndclass.hIconSm=0; 
  99.     
  100.     RegisterClassEx(&wndclass);
  101.     
  102.     m_hWnd = CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
  103.     if (!m_hWnd)
  104.         return false;
  105.     SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this);
  106.  
  107.     hMainWnd = m_hWnd;
  108.  
  109.     m_pOptions = new COptions;
  110.     m_pFileLogger = new CFileLogger(m_pOptions);
  111.     
  112.     //Create the threads
  113.     int num = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
  114.     for (int i = 0; i < num; i++)
  115.     {
  116.         int index = GetNextThreadNotificationID();
  117.         CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
  118.         m_ThreadNotificationIDs[index] = pThread;
  119.         if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
  120.         {
  121.             pThread->ResumeThread();
  122.             m_ThreadArray.push_back(pThread);
  123.         }
  124.     }
  125.     
  126.     m_pFileLogger->Log(GetVersionString() + " started");
  127.     m_pFileLogger->Log("Initializing Server.");
  128.  
  129.     m_nTimerID = SetTimer(m_hWnd, 1234, 10000, NULL);
  130.     ASSERT(m_nTimerID);
  131.  
  132.     if (CreateListenSocket())
  133.     {
  134.         m_nServerState = STATE_ONLINE;
  135.         ShowStatus("Server online.", 0);
  136.     }
  137.     else
  138.         ShowStatus("Server not online.", 1);
  139.  
  140.     CreateAdminListenSocket();
  141.  
  142.     return true;
  143. }
  144.  
  145. HWND CServer::GetHwnd()
  146. {
  147.     return m_hWnd;
  148. }
  149.  
  150. LRESULT CALLBACK CServer::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  151. {
  152.     CServer *pServer=(CServer *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  153.  
  154.     if (message == WM_CLOSE)
  155.     {
  156.         pServer->OnClose();
  157.         return 0;
  158.     }
  159.     else if (hWnd && message == WM_DESTROY)
  160.     {
  161.         ASSERT( hWnd == pServer->m_hWnd);
  162.         HANDLE *handle = new HANDLE[pServer->m_ThreadArray.size()];
  163.         unsigned int i = 0;
  164.         std::list<CServerThread *>::iterator iter;
  165.         for (iter = pServer->m_ThreadArray.begin(); iter != pServer->m_ThreadArray.end(); iter++, i++)
  166.         {
  167.             handle[i]=(*iter)->m_hThread;
  168.             (*iter)->PostThreadMessage(WM_QUIT, 0, 0);
  169.         }
  170.         for (i=0; i<pServer->m_ThreadArray.size(); i++)
  171.         {
  172.             int res=WaitForSingleObject(handle[i],INFINITE);
  173.             if (res==WAIT_FAILED)
  174.                 res=GetLastError();
  175.         }
  176.         delete [] handle;
  177.         handle = new HANDLE[pServer->m_ClosedThreads.size()];
  178.         i=0;
  179.         for (iter = pServer->m_ClosedThreads.begin(); iter != pServer->m_ClosedThreads.end(); iter++, i++)
  180.         {
  181.             handle[i]=(*iter)->m_hThread;
  182.             (*iter)->PostThreadMessage(WM_QUIT, 0, 0);
  183.         }
  184.         for (i = 0; i < pServer->m_ClosedThreads.size(); i++)
  185.         {
  186.             int res=WaitForSingleObject(handle[i],INFINITE);
  187.             if (res==WAIT_FAILED)
  188.                 res=GetLastError();
  189.         }
  190.         delete [] handle;
  191.         for (std::list<CAdminListenSocket*>::iterator iter2 = pServer->m_AdminListenSocketList.begin(); iter2!=pServer->m_AdminListenSocketList.end(); iter2++)
  192.         {
  193.             (*iter2)->Close();
  194.             delete *iter2;
  195.         }
  196.         pServer->m_AdminListenSocketList.clear();
  197.         delete pServer->m_pAdminInterface;
  198.         pServer->m_pAdminInterface = NULL;
  199.         delete pServer->m_pOptions;
  200.         pServer->m_pOptions = NULL;
  201.         if (pServer->m_nTimerID)
  202.             KillTimer(pServer->m_hWnd, pServer->m_nTimerID);
  203.         PostQuitMessage(0);
  204.         return 0;
  205.     }
  206.     else if (message == WM_TIMER)
  207.         pServer->OnTimer(wParam);
  208.     else if (message == WM_FILEZILLA_RELOADCONFIG)
  209.     {
  210.         COptions options;
  211.         options.ReloadConfig();
  212.         CPermissions perm;
  213.         perm.ReloadConfig();
  214.     }
  215.     else if (message >= WM_FILEZILLA_SERVERMSG)
  216.     {
  217.         UINT index = message - WM_FILEZILLA_SERVERMSG;
  218.         if (index >= pServer->m_ThreadNotificationIDs.size())
  219.             return 0;
  220.  
  221.         CServerThread *pThread = pServer->m_ThreadNotificationIDs[index];
  222.         if (pThread)
  223.         {
  224.             std::list<CServerThread::t_Notification> notifications;
  225.             pThread->GetNotifications(notifications);
  226.             for (std::list<CServerThread::t_Notification>::const_iterator iter = notifications.begin(); iter != notifications.end(); iter++)
  227.                 if (pServer->OnServerMessage(pThread, iter->wParam, iter->lParam) != 0)
  228.                     break;
  229.         }
  230.         return 0;
  231.     }
  232.     
  233.     return ::DefWindowProc(hWnd, message, wParam, lParam);
  234. }
  235.  
  236. LRESULT CServer::OnServerMessage(CServerThread* pThread, WPARAM wParam, LPARAM lParam)
  237. {
  238.     if (wParam == FSM_STATUSMESSAGE)
  239.     {
  240.         t_statusmsg *msg = reinterpret_cast<t_statusmsg *>(lParam);
  241.         if (!msg)
  242.             return 0;
  243.  
  244.         CStdString str;
  245.  
  246.         FILETIME fFileTime;
  247.         SystemTimeToFileTime(&msg->time, &fFileTime);
  248.         
  249.         str.Format("(%06d)- %s (%s)> %s", msg->userid, (LPCTSTR)msg->user, (LPCTSTR)msg->ip, (LPCTSTR)msg->status);
  250.         ShowStatus(fFileTime.dwHighDateTime, fFileTime.dwLowDateTime, str, msg->type);
  251.         delete [] msg->user;
  252.         delete [] msg->status;
  253.         delete msg;
  254.     }
  255.     else if (wParam == FSM_CONNECTIONDATA)
  256.     {
  257.         t_connop *pConnOp = reinterpret_cast<t_connop*>(lParam);
  258.         if (!pConnOp)
  259.             return 0;
  260.         
  261.         int len;
  262.         unsigned char *buffer;
  263.  
  264.         switch (pConnOp->op)
  265.         {
  266.         case USERCONTROL_CONNOP_ADD:
  267.             {
  268.                 t_connectiondata_add* pData = (t_connectiondata_add*)pConnOp->data;
  269.                 t_connectiondata data;
  270.                 data.userid = pConnOp->userid;
  271.                 data.pThread = pThread;
  272.                 strncpy(data.ip, pData->ip, 16);
  273.                 data.port = pData->port;
  274.                 data.transferMode = 0;
  275.                 data.currentOffset = 0;
  276.                 data.totalSize = -1;
  277.  
  278.                 m_UsersList[pConnOp->userid] = data;
  279.  
  280.                 int iplen = strlen(pData->ip);
  281.                 len = 2 + 4 + 2 + iplen + 4;
  282.                 buffer = new unsigned char[len];
  283.                 buffer[2 + 4] = iplen / 256;
  284.                 buffer[2 + 4 + 1] = iplen % 256;        
  285.                 memcpy(buffer + 2 + 4 + 2, pData->ip, iplen);
  286.                 memcpy(buffer + 2 + 4 + 2 + iplen, &pData->port, 4);
  287.  
  288.                 delete pData;
  289.             }
  290.             break;
  291.         case USERCONTROL_CONNOP_CHANGEUSER:
  292.             {
  293.                 t_connectiondata_changeuser* pData = (t_connectiondata_changeuser*)pConnOp->data;
  294.                 m_UsersList[pConnOp->userid].user = pData->user;
  295.             
  296.                 int userlen = pData->user.GetLength();
  297.                 len = 2 + 4 + 2 + userlen;
  298.                 buffer = new unsigned char[len];
  299.                 buffer[2 + 4] = userlen / 256;
  300.                 buffer[2 + 4 + 1] = userlen % 256;        
  301.                 memcpy(buffer + 2 + 4 + 2, pData->user, userlen);
  302.  
  303.                 delete pData;
  304.             }
  305.             break;
  306.         case USERCONTROL_CONNOP_REMOVE:
  307.             {
  308.                 std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(pConnOp->userid);
  309.                 if (iter!=m_UsersList.end())
  310.                     m_UsersList.erase(iter);
  311.  
  312.                 len = 6;
  313.                 buffer = new unsigned char[len];
  314.             }
  315.             break;
  316.         case USERCONTROL_CONNOP_TRANSFERINIT:
  317.             {
  318.                 t_connectiondata_transferinfo* pData = (t_connectiondata_transferinfo*)pConnOp->data;
  319.                 t_connectiondata& data = m_UsersList[pConnOp->userid];
  320.                 data.transferMode = pData->transferMode;
  321.                 data.physicalFile = pData->physicalFile;
  322.                 data.logicalFile = pData->logicalFile;
  323.                 data.currentOffset = pData->startOffset;
  324.                 data.totalSize = pData->totalSize;
  325.  
  326.                 if (data.transferMode)
  327.                 {
  328.                     int physicalFileLen = pData->physicalFile.GetLength();
  329.                     int logicalFileLen = pData->logicalFile.GetLength();
  330.                     len = 2 + 4 + 1 + 2 + physicalFileLen + 2 + logicalFileLen;
  331.                     if (data.currentOffset != 0)
  332.                         len += 8;
  333.                     if (data.totalSize != -1)
  334.                         len += 8;
  335.  
  336.                     buffer = new unsigned char[len];
  337.                     unsigned char *p = buffer + 6;
  338.                     *p = data.transferMode;
  339.                     
  340.                     // Bit 5 and 6 indicate presence of currentOffset and totalSize.
  341.                     if (data.currentOffset != 0)
  342.                         *p |= 0x20;
  343.                     if (data.totalSize != -1)
  344.                         *p |= 0x40;
  345.                     p++;
  346.                     
  347.                     *p++ = physicalFileLen / 256;
  348.                     *p++ = physicalFileLen % 256;        
  349.                     memcpy(p, data.physicalFile.c_str(), physicalFileLen);
  350.                     p += physicalFileLen;
  351.  
  352.                     *p++ = logicalFileLen / 256;
  353.                     *p++ = logicalFileLen % 256;        
  354.                     memcpy(p, data.logicalFile.c_str(), logicalFileLen);
  355.                     p += logicalFileLen;
  356.  
  357.                     if (data.currentOffset != 0)
  358.                     {
  359.                         memcpy(p, &data.currentOffset, 8);
  360.                         p += 8;
  361.                     }
  362.                     if (data.totalSize != -1)
  363.                     {
  364.                         memcpy(p, &data.totalSize, 8);
  365.                         p += 8;
  366.                     }
  367.                 }
  368.                 else
  369.                 {
  370.                     len = 2 + 4 + 1;
  371.                     buffer = new unsigned char[len];
  372.                     buffer[2 + 4] = 0;
  373.                 }
  374.                 delete pData;
  375.             }
  376.             break;
  377.         case USERCONTROL_CONNOP_TRANSFEROFFSETS:
  378.             {
  379.                 t_connectiondata_transferoffsets* pData = (t_connectiondata_transferoffsets*)pConnOp->data;
  380.                 buffer = pData->pData;
  381.                 len = pData->len;
  382.  
  383.                 unsigned char* p = buffer + 2;
  384.                 int* userid;
  385.                 __int64* offset;
  386.                 while ((p - buffer + 12) <= len)
  387.                 {
  388.                     userid = (int*)p;
  389.                     offset = (__int64*)(p + 4);
  390.                     t_connectiondata& data = m_UsersList[*userid];
  391.                     data.currentOffset = *offset;
  392.  
  393.                     p += 12;                    
  394.                 }
  395.                 delete pData;
  396.             }
  397.             break;
  398.         }
  399.         buffer[0] = USERCONTROL_CONNOP;
  400.         buffer[1] = pConnOp->op;
  401.         if (pConnOp->op != USERCONTROL_CONNOP_TRANSFEROFFSETS)
  402.             memcpy(buffer + 2, &pConnOp->userid, 4);
  403.         
  404.         m_pAdminInterface->SendCommand(2, 3, buffer, len);
  405.         delete [] buffer;
  406.         delete pConnOp;
  407.     }
  408.     else if (wParam == FSM_THREADCANQUIT)
  409.     {
  410.         std::list<CServerThread *>::iterator iter;
  411.         for (iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++)
  412.         {
  413.             if (*iter == pThread)
  414.             {
  415.                 HANDLE handle=pThread->m_hThread;
  416.                 pThread->PostThreadMessage(WM_QUIT, 0, 0);
  417.                 int res=WaitForSingleObject(handle, INFINITE);
  418.                 if (res==WAIT_FAILED)
  419.                     res=GetLastError();
  420.                 m_ThreadArray.erase(iter);
  421.                 FreeThreadNotificationID(pThread);
  422.                 if (!m_ThreadArray.size() && !m_ClosedThreads.size())
  423.                 {
  424.                     m_nServerState &= ~(STATE_ONLINE | STATE_MASK_GOOFFLINE);
  425.                     SendState();
  426.                     if (!m_bQuit)
  427.                         ShowStatus(_T("Server offline."), 1);
  428.                     else
  429.                         DestroyWindow(m_hWnd);
  430.                 }
  431.                 return -1;
  432.             }
  433.         }
  434.         for (iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  435.         {
  436.             if (*iter == pThread)
  437.             {
  438.                 HANDLE handle = pThread->m_hThread;
  439.                 pThread->PostThreadMessage(WM_QUIT, 0, 0);
  440.                 int res = WaitForSingleObject(handle, INFINITE);
  441.                 if (res == WAIT_FAILED)
  442.                     res = GetLastError();
  443.                 m_ClosedThreads.erase(iter);
  444.                 FreeThreadNotificationID(pThread);
  445.                 if (!m_ThreadArray.size() && !m_ClosedThreads.size())
  446.                 {
  447.                     m_nServerState &= ~(STATE_ONLINE | STATE_MASK_GOOFFLINE);
  448.                     SendState();
  449.                     if (!m_bQuit)
  450.                         ShowStatus(_T("Server offline."), 1);
  451.                     else
  452.                         DestroyWindow(m_hWnd);
  453.                 }
  454.                 return -1;
  455.             }
  456.             
  457.         }
  458.     }
  459.     else if (wParam == FSM_SEND)
  460.     {
  461.         char buffer[5];
  462.         buffer[0] = 1;
  463.         memcpy(buffer+1, &lParam, 4);
  464.         m_pAdminInterface->SendCommand(2, 7, buffer, 5);
  465.         m_nSendCount += lParam;
  466.     }
  467.     else if (wParam == FSM_RECV)
  468.     {
  469.         char buffer[5];
  470.         buffer[0] = 0;
  471.         memcpy(buffer+1, &lParam, 4);
  472.         m_pAdminInterface->SendCommand(2, 7, buffer, 5);
  473.         m_nRecvCount += lParam;
  474.     }
  475.     return 0;
  476. }
  477.  
  478.  
  479. void CServer::OnClose()
  480. {
  481.     for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); listIter++)
  482.     {
  483.         (*listIter)->Close();
  484.         delete *listIter;
  485.     }
  486.     m_ListenSocketList.clear();
  487.  
  488.     m_bQuit = TRUE;
  489.  
  490.     if (!m_ThreadArray.size() && !m_ClosedThreads.size())
  491.     {
  492.         DestroyWindow(m_hWnd);
  493.         return;
  494.     }
  495.  
  496.     std::list<CServerThread *>::iterator iter;
  497.     for (iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++)
  498.     {
  499.         VERIFY((*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0));
  500.     }
  501.     for (iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  502.     {
  503.         VERIFY((*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0));
  504.     }
  505. }
  506.  
  507. BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength)
  508. {
  509.     switch (nID)
  510.     {
  511.     case 2:
  512.         if (!nDataLength)
  513.         {
  514.             unsigned char buffer[2];
  515.             buffer[0] = m_nServerState / 256;
  516.             buffer[1] = m_nServerState % 256;
  517.             pAdminSocket->SendCommand(1, 2, buffer, 2);
  518.         }
  519.         else if (nDataLength == 2)
  520.         {
  521.             ToggleActive(*pData * 256 + pData[1]);
  522.             unsigned char buffer[2];
  523.             buffer[0] = m_nServerState / 256;
  524.             buffer[1] = m_nServerState % 256;
  525.             pAdminSocket->SendCommand(1, 2, buffer, 2);
  526.         }
  527.         else
  528.             pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
  529.         break;
  530.     case 3:
  531.         if (!nDataLength)
  532.             pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
  533.         else if (*pData == USERCONTROL_GETLIST)
  534.         {
  535.             int len = 3;
  536.             std::map<int, t_connectiondata>::iterator iter;
  537.             for (iter=m_UsersList.begin(); iter!=m_UsersList.end(); iter++)
  538.             {
  539.                 const t_connectiondata& data = iter->second;
  540.                 len += 4 + strlen(data.ip) + 2 + 4 + strlen(data.user) + 2 + 
  541.                        1;
  542.                 if (data.transferMode)
  543.                 {
  544.                     len += 2 + data.physicalFile.GetLength() + 2 + data.logicalFile.GetLength();
  545.  
  546.                     if (data.currentOffset != 0)
  547.                         len += 8;
  548.                     if (data.totalSize != -1)
  549.                         len += 8;
  550.                 }
  551.             }
  552.             unsigned char *buffer = new unsigned char[len];
  553.             buffer[0] = USERCONTROL_GETLIST;
  554.             buffer[1] = m_UsersList.size() / 256;
  555.             buffer[2] = m_UsersList.size() % 256;
  556.             unsigned char *p = buffer + 3;
  557.             for (iter = m_UsersList.begin(); iter != m_UsersList.end(); iter++)
  558.             {
  559.                 const t_connectiondata& data = iter->second;
  560.                 USES_CONVERSION;
  561.                 memcpy(p, &data.userid, 4);
  562.                 p+=4;
  563.                 *p++ = strlen(data.ip) / 256;
  564.                 *p++ = strlen(data.ip) % 256;
  565.                 memcpy(p, T2CA(data.ip), strlen(T2CA(data.ip)));
  566.                 p+=strlen(T2CA(data.ip));
  567.  
  568.                 memcpy(p, &data.port, 4);
  569.                 p+=4;
  570.  
  571.                 if (data.user)
  572.                 {
  573.                     *p++ = strlen(data.user) / 256;
  574.                     *p++ = strlen(data.user) % 256;
  575.                     memcpy(p, T2CA(data.user), strlen(T2CA(data.user)));
  576.                     p += strlen(T2CA(data.user));
  577.                 }
  578.                 else
  579.                 {
  580.                     *p++ = 0;
  581.                     *p++ = 0;
  582.                 }
  583.                 *p = data.transferMode;
  584.                 if (data.transferMode)
  585.                 {
  586.                     // Bit 5 and 6 indicate presence of currentOffset and totalSize.
  587.                     if (data.currentOffset != 0)
  588.                         *p |= 0x20;
  589.                     if (data.totalSize != -1)
  590.                         *p |= 0x40;
  591.                     p++;
  592.                     int physicalLen = data.physicalFile.GetLength();
  593.                     *p++ = physicalLen / 256;
  594.                     *p++ = physicalLen % 256;
  595.                     memcpy(p, T2CA(data.physicalFile), physicalLen);
  596.                     p += physicalLen;
  597.  
  598.                     int logicalLen = data.logicalFile.GetLength();
  599.                     *p++ = logicalLen / 256;
  600.                     *p++ = logicalLen % 256;
  601.                     memcpy(p, T2CA(data.logicalFile), logicalLen);
  602.                     p += logicalLen;
  603.  
  604.                     if (data.currentOffset != 0)
  605.                     {
  606.                         memcpy(p, &data.currentOffset, 8);
  607.                         p += 8;
  608.                     }
  609.                     if (data.totalSize != -1)
  610.                     {
  611.                         memcpy(p, &data.totalSize, 8);
  612.                         p += 8;
  613.                     }
  614.                 }
  615.                 else
  616.                     p++;
  617.             }
  618.             m_pAdminInterface->SendCommand(1, 3, buffer, len);            
  619.             delete [] buffer;
  620.         }
  621.         else if (*pData == USERCONTROL_KICK)
  622.         {
  623.             if (nDataLength != 5)
  624.                 pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
  625.             else
  626.             {
  627.                 int nUserID;
  628.                 memcpy(&nUserID, pData+1, 4);
  629.                 
  630.                 std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID);
  631.                 if (iter!=m_UsersList.end())
  632.                 {
  633.                     t_controlmessage *msg=new t_controlmessage;
  634.                     msg->command=USERCONTROL_KICK;
  635.                     msg->socketid=nUserID;
  636.                     iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg);
  637.                     char buffer[2];
  638.                     buffer[0] = USERCONTROL_KICK;
  639.                     buffer[1] = 0;
  640.                     pAdminSocket->SendCommand(1, 3, &buffer, 2);
  641.                 }
  642.                 else
  643.                 {
  644.                     char buffer[2];
  645.                     buffer[0] = USERCONTROL_KICK;
  646.                     buffer[1] = 1;
  647.                     pAdminSocket->SendCommand(1, 3, &buffer, 2);
  648.                 }
  649.             }
  650.         }
  651.         else
  652.             pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data")+1);
  653.         break;
  654.     case 5:
  655.         if (!nDataLength)
  656.         {
  657.             char *pBuffer = NULL;
  658.             DWORD nBufferLength = 0;
  659.             if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength))
  660.             {
  661.                 pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength);
  662.                 delete [] pBuffer;
  663.             }
  664.         }
  665.         else if (m_pOptions)
  666.         {
  667.             if (nDataLength < 2)
  668.                 pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
  669.             else
  670.             {
  671.                 CString listenPorts = m_pOptions->GetOption(OPTION_SERVERPORT);
  672.                 CString listenPortsSsl = m_pOptions->GetOption(OPTION_SSLPORTS);
  673.                 bool enableSsl = m_pOptions->GetOptionVal(OPTION_ENABLESSL) != 0;
  674.                 int nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT);
  675.                 CStdString adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);
  676.                 
  677.                 SOCKADDR_IN sockAddr;
  678.                 memset(&sockAddr, 0, sizeof(sockAddr));
  679.                 int nSockAddrLen = sizeof(sockAddr);    
  680.                 BOOL bLocal = pAdminSocket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen) && sockAddr.sin_addr.S_un.S_addr == 0x0100007f;
  681.  
  682.                 if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal))
  683.                 {
  684.                     pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1);
  685.                     char buffer = 1;
  686.                     pAdminSocket->SendCommand(1, 5, &buffer, 1);
  687.                     break;
  688.                 }
  689.  
  690.                 char buffer = 0;
  691.                 pAdminSocket->SendCommand(1, 5, &buffer, 1);
  692.  
  693.                 unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
  694.                 if (threadnum > m_ThreadArray.size())
  695.                 {
  696.                     int newthreads=threadnum-m_ThreadArray.size();
  697.                     for (int i = 0; i < newthreads; i++)
  698.                     {
  699.                         int index = GetNextThreadNotificationID();
  700.                         CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
  701.                         m_ThreadNotificationIDs[index] = pThread;
  702.                         if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
  703.                         {
  704.                             pThread->ResumeThread();
  705.                             m_ThreadArray.push_back(pThread);
  706.                         }
  707.                     }
  708.                     CStdString str;
  709.                     str.Format("Number of threads increased to %d.", threadnum);
  710.                     ShowStatus(str, 0);
  711.                 }
  712.                 else if (threadnum < m_ThreadArray.size())
  713.                 {
  714.                     CStdString str;
  715.                     str.Format("Decreasing number of threads to %d.", threadnum);
  716.                     ShowStatus(str, 0);
  717.                     unsigned int i=0;
  718.                     std::list<CServerThread *> newList;
  719.                     for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++,i++)
  720.                         if (i>=threadnum)
  721.                         {
  722.                             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
  723.                             m_ClosedThreads.push_back(*iter);
  724.                         }
  725.                         else
  726.                             newList.push_back(*iter);
  727.                     m_ThreadArray.clear();
  728.                     m_ThreadArray = newList;
  729.                 }
  730.                 if (listenPorts != m_pOptions->GetOption(OPTION_SERVERPORT) ||
  731.                     enableSsl != (m_pOptions->GetOptionVal(OPTION_ENABLESSL) != 0) ||
  732.                     (m_pOptions->GetOptionVal(OPTION_ENABLESSL) && listenPortsSsl != m_pOptions->GetOption(OPTION_SSLPORTS)))
  733.                 {
  734.                     if (!m_ListenSocketList.empty())
  735.                     {
  736.                         ShowStatus("Closing all listening sockets", 0);
  737.                         for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); listIter++)
  738.                         {
  739.                             (*listIter)->Close();
  740.                             delete *listIter;
  741.                         }
  742.                         m_ListenSocketList.clear();
  743.  
  744.                         if (!CreateListenSocket())
  745.                         {
  746.                             ShowStatus("Failed to create a listen socket on any of the specified ports. Server is not online!", 1);
  747.                             m_nServerState &= ~STATE_ONLINE;
  748.                         }
  749.                         else
  750.                         {
  751.                             ShowStatus("Listen socket port changed",0);
  752.                             if (!(m_nServerState & STATE_MASK_GOOFFLINE))
  753.                                 m_nServerState |= STATE_ONLINE;
  754.                         }
  755.                     }
  756.                 }
  757.                 if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings!=m_pOptions->GetOption(OPTION_ADMINIPBINDINGS))
  758.                 {
  759.                     if (nAdminListenPort == m_pOptions->GetOptionVal(OPTION_ADMINPORT))
  760.                     {
  761.                         for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++)
  762.                         {
  763.                             (*iter)->Close();
  764.                             delete *iter;
  765.                         }
  766.                         m_AdminListenSocketList.clear();
  767.                     }
  768.                     CAdminListenSocket *pSocket = new CAdminListenSocket(m_pAdminInterface);
  769.                     if (!pSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)!="*") ? _T("127.0.0.1") : NULL))
  770.                     {
  771.                         delete pSocket;
  772.                         CStdString str;
  773.                         str.Format(_T("Failed to change admin listen port to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT));
  774.                         m_pOptions->SetOption(OPTION_ADMINPORT, nAdminListenPort);
  775.                         ShowStatus(str, 1);
  776.                     }
  777.                     else
  778.                     {
  779.                         pSocket->Listen();
  780.                         for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++)
  781.                         {
  782.                             (*iter)->Close();
  783.                             delete *iter;
  784.                         }
  785.                         m_AdminListenSocketList.clear();
  786.  
  787.                         m_AdminListenSocketList.push_back(pSocket);
  788.                         if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT))
  789.                         {
  790.                             CStdString str;
  791.                             str.Format(_T("Admin listen port changed to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT));
  792.                             ShowStatus(str, 0);
  793.                         }
  794.  
  795.                         if (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS) != "*")
  796.                         {
  797.                             BOOL bError = FALSE;
  798.                             CStdString str = _T("Failed to bind the admin interface to the following IPs:");
  799.                             CStdString ipBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);
  800.  
  801.                             if (ipBindings != "")
  802.                                 ipBindings += " ";
  803.                             while (ipBindings != "")
  804.                             {
  805.                                 int pos = ipBindings.Find(" ");
  806.                                 if (pos == -1)
  807.                                     break;
  808.                                 CStdString ip = ipBindings.Left(pos);
  809.                                 ipBindings = ipBindings.Mid(pos+1);
  810.                                 CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface);
  811.                                 if (!pAdminListenSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, ip) || !pAdminListenSocket->Listen())
  812.                                 {
  813.                                     bError = TRUE;
  814.                                     str += _T(" ") + ip;
  815.                                     delete pAdminListenSocket;
  816.                                 }
  817.                                 else
  818.                                     m_AdminListenSocketList.push_back(pAdminListenSocket);
  819.                             }
  820.                             if (bError)
  821.                                 ShowStatus(str, 1);
  822.                         }
  823.                         if (adminIpBindings!=m_pOptions->GetOption(OPTION_ADMINIPBINDINGS))
  824.                             ShowStatus(_T("Admin interface IP bindings changed"), 0);
  825.                     }
  826.     
  827.                 }
  828.             }
  829.         }
  830.         break;
  831.     case 6:
  832.         if (!nDataLength)
  833.         {
  834.             char *pBuffer = NULL;
  835.             DWORD nBufferLength = 0;
  836.             CPermissions permissions;
  837.             permissions.GetAsCommand(&pBuffer, &nBufferLength);
  838.             pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength);
  839.             delete [] pBuffer;
  840.         }
  841.         else
  842.         {
  843.             if (nDataLength < 2)
  844.                 pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
  845.             else
  846.             {
  847.                 CPermissions permissions;
  848.                 if (!permissions.ParseUsersCommand(pData, nDataLength))
  849.                 {
  850.                     pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1);
  851.                     char buffer = 1;
  852.                     pAdminSocket->SendCommand(1, 6, &buffer, 1);
  853.                     break;
  854.                 }
  855.                 char buffer = 0;
  856.                 pAdminSocket->SendCommand(1, 6, &buffer, 1);
  857.             }
  858.         }
  859.         break;
  860.     case 8:
  861.         pAdminSocket->SendCommand(1, 8, NULL, 0);
  862.         break;
  863.     default:
  864.         {
  865.             CStdString str;
  866.             str.Format("\001Protocol error: Unknown command (%d).", nID);
  867.             pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength());
  868.         }
  869.         break;
  870.     }
  871.  
  872.     return TRUE;
  873. }
  874.  
  875. BOOL CServer::ToggleActive(int nServerState)
  876. {
  877.     if (nServerState & STATE_GOOFFLINE_NOW)
  878.     {
  879.         if (m_nServerState & STATE_MASK_GOOFFLINE)
  880.             return FALSE;
  881.  
  882.         for (std::list<CListenSocket*>::iterator listenIter = m_ListenSocketList.begin(); listenIter != m_ListenSocketList.end(); listenIter++)
  883.         {
  884.             (*listenIter)->Close();
  885.             delete *listenIter;
  886.         }
  887.         m_ListenSocketList.clear();
  888.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  889.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0);
  890.         for (std::list<CServerThread *>::iterator iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++)
  891.         {
  892.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0);
  893.             m_ClosedThreads.push_back(*iter);
  894.         }
  895.         m_ThreadArray.clear();
  896.         m_nServerState &= ~STATE_ONLINE;
  897.         if (!m_ClosedThreads.empty())
  898.             m_nServerState |= STATE_GOOFFLINE_NOW;
  899.     }
  900.     else if (nServerState & STATE_GOOFFLINE_LOGOUT)
  901.     {
  902.         if (m_nServerState & STATE_MASK_GOOFFLINE)
  903.             return FALSE;
  904.  
  905.         for (std::list<CListenSocket*>::iterator listenIter = m_ListenSocketList.begin(); listenIter != m_ListenSocketList.end(); listenIter++)
  906.         {
  907.             (*listenIter)->Close();
  908.             delete *listenIter;
  909.         }
  910.         m_ListenSocketList.clear();
  911.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  912.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
  913.         for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++)
  914.         {
  915.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);            
  916.             m_ClosedThreads.push_back(*iter);
  917.         }
  918.         m_ThreadArray.clear();
  919.         m_nServerState &= ~STATE_ONLINE;
  920.         if (!m_ClosedThreads.empty())
  921.             m_nServerState = m_nServerState |= STATE_GOOFFLINE_LOGOUT;
  922.     }
  923.     else if (nServerState & STATE_GOOFFLINE_WAITTRANSFER)
  924.     {
  925.         if (m_nServerState & STATE_MASK_GOOFFLINE)
  926.             return FALSE;
  927.  
  928.         for (std::list<CListenSocket*>::iterator listenIter = m_ListenSocketList.begin(); listenIter != m_ListenSocketList.end(); listenIter++)
  929.         {
  930.             (*listenIter)->Close();
  931.             delete *listenIter;
  932.         }
  933.         m_ListenSocketList.clear();
  934.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  935.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 1);
  936.         for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++)
  937.         {
  938.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 1);            
  939.             m_ClosedThreads.push_back(*iter);
  940.         }
  941.         m_ThreadArray.clear();
  942.         m_nServerState &= ~STATE_ONLINE;
  943.         if (!m_ClosedThreads.empty())
  944.             m_nServerState = m_nServerState |= STATE_GOOFFLINE_WAITTRANSFER;
  945.     }
  946.     else if (nServerState & STATE_ONLINE)
  947.     {
  948.         if (m_ListenSocketList.empty())
  949.             CreateListenSocket();
  950.  
  951.         if (!m_ListenSocketList.empty())
  952.         {
  953.             ShowStatus("Server online", 0);
  954.             int i=0;
  955.             int num = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_THREADNUM) : 2);
  956.  
  957.             //Recreate the threads
  958.             for (i = m_ThreadArray.size(); i < num; i++)
  959.             {
  960.                 int index = GetNextThreadNotificationID();
  961.                 CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
  962.                 m_ThreadNotificationIDs[index] = pThread;
  963.                 if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
  964.                 {
  965.                     m_ThreadArray.push_back(pThread);
  966.                     pThread->ResumeThread();
  967.                 }
  968.             }
  969.         }
  970.         for (std::list<CListenSocket *>::iterator iter = m_ListenSocketList.begin(); iter != m_ListenSocketList.end(); iter++)
  971.             (*iter)->m_bLocked = nServerState & STATE_LOCKED;
  972.  
  973.         // Set closing threads to "wait until logout" mode.
  974.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  975.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
  976.  
  977.         m_nServerState = (m_ListenSocketList.empty() ? 0 : STATE_ONLINE) + (nServerState & STATE_LOCKED);
  978.     }
  979.  
  980.     SendState();
  981.     return TRUE;
  982. }
  983.  
  984. void CServer::ShowStatus(LPCTSTR msg, int nType)
  985. {
  986.     USES_CONVERSION;
  987.     LPCSTR str=T2CA(msg);
  988.     char *pBuffer=new char[strlen(str)+1];
  989.     *pBuffer=nType;
  990.     memcpy(pBuffer+1, str, strlen(str));
  991.     if (m_pAdminInterface)
  992.         m_pAdminInterface->SendCommand(2, 1, pBuffer, strlen(str)+1);
  993.     delete [] pBuffer;
  994.  
  995.     if (m_pFileLogger)
  996.         m_pFileLogger->Log(msg);
  997. }
  998.  
  999. void CServer::ShowStatus(DWORD eventDateHigh, DWORD eventDateLow, LPCTSTR msg, int nType)
  1000. {
  1001.     USES_CONVERSION;
  1002.     LPCSTR str = T2CA(msg);
  1003.     char *pBuffer = new char[strlen(str) + 1 + 8];
  1004.     *pBuffer = nType;
  1005.     memcpy(pBuffer + 1, &eventDateHigh, 8);
  1006.     memcpy(pBuffer + 5, &eventDateLow, 4);
  1007.     memcpy(pBuffer + 1 + 8, str, strlen(str));
  1008.     if (m_pAdminInterface)
  1009.         m_pAdminInterface->SendCommand(2, 4, pBuffer, strlen(str) + 1 + 8);
  1010.     delete [] pBuffer;
  1011.  
  1012.     //Log string
  1013.     if (m_pFileLogger)
  1014.     {
  1015.         FILETIME fFileTime;
  1016.         SYSTEMTIME sFileTime;
  1017.         fFileTime.dwHighDateTime = eventDateHigh;
  1018.         fFileTime.dwLowDateTime = eventDateLow;
  1019.         FileTimeToSystemTime(&fFileTime, &sFileTime);
  1020.         char text[80];
  1021.         if (!GetDateFormat(
  1022.             LOCALE_USER_DEFAULT,               // locale for which date is to be formatted
  1023.             DATE_SHORTDATE,             // flags specifying function options
  1024.             &sFileTime,  // date to be formatted
  1025.             0,          // date format string
  1026.             text,          // buffer for storing formatted string
  1027.             80                // size of buffer
  1028.             ))
  1029.             return;
  1030.         
  1031.         CStdString text2=" ";
  1032.         text2+=text;
  1033.         
  1034.         if (!GetTimeFormat(
  1035.             LOCALE_USER_DEFAULT,               // locale for which date is to be formatted
  1036.             TIME_FORCE24HOURFORMAT,             // flags specifying function options
  1037.             &sFileTime,  // date to be formatted
  1038.             0,          // date format string
  1039.             text,          // buffer for storing formatted string
  1040.             80                // size of buffer
  1041.             ))
  1042.             return;
  1043.  
  1044.         text2 += " ";
  1045.         text2 += text;
  1046.         CStdString str = msg;
  1047.         int pos = str.Find("-");
  1048.         if (pos!=-1)
  1049.         {
  1050.             str.Insert(pos, text2 + " ");
  1051.         }
  1052.         m_pFileLogger->Log(str);
  1053.     }
  1054. }
  1055.  
  1056. void CServer::OnTimer(UINT nIDEvent)
  1057. {
  1058.     m_pAdminInterface->CheckForTimeout();
  1059.     m_pFileLogger->CheckLogFile();
  1060. }
  1061.  
  1062. BOOL CServer::CreateAdminListenSocket()
  1063. {
  1064.     CStdString ipBindings = (m_pOptions ? m_pOptions->GetOption(OPTION_ADMINIPBINDINGS) : "");
  1065.     int nAdminPort = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT) : 14147);
  1066.     CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface);
  1067.     BOOL bError = FALSE;
  1068.     if (!pAdminListenSocket->Create(nAdminPort, SOCK_STREAM, FD_ACCEPT, (ipBindings!="*") ? _T("127.0.0.1") : NULL))
  1069.     {
  1070.         CStdString str;
  1071.         if (!pAdminListenSocket->Create(0, SOCK_STREAM, FD_ACCEPT, _T("127.0.0.1")))
  1072.         {
  1073.             delete pAdminListenSocket;
  1074.             pAdminListenSocket = NULL;
  1075.             str.Format(_T("Failed to create listen socket for admin interface on port %d, the admin interface has been disabled."), nAdminPort);
  1076.         }
  1077.         else
  1078.         {
  1079.             SOCKADDR_IN sockAddr;
  1080.             memset(&sockAddr, 0, sizeof(sockAddr));
  1081.             int nSockAddrLen = sizeof(sockAddr);
  1082.             BOOL bResult = pAdminListenSocket->GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  1083.             if (bResult)
  1084.             {
  1085.                 int nPort = ntohs(sockAddr.sin_port);
  1086.                 str.Format(_T("Failed to create listen socket for admin interface on port %d, for this session the admin interface is available on port %d."), nAdminPort, nPort);
  1087.                 nAdminPort = nPort;
  1088.             }
  1089.             else
  1090.             {
  1091.                 delete pAdminListenSocket;
  1092.                 pAdminListenSocket = NULL;
  1093.                 str.Format(_T("Failed to create listen socket for admin interface on port %d, the admin interface has been disabled."), nAdminPort);
  1094.             }
  1095.         }
  1096.         MessageBox(0, str, _T("FileZilla Server Error"), MB_ICONEXCLAMATION | MB_SERVICE_NOTIFICATION);
  1097.     }
  1098.     if (pAdminListenSocket)
  1099.     {
  1100.         VERIFY(pAdminListenSocket->Listen());
  1101.         m_AdminListenSocketList.push_back(pAdminListenSocket);
  1102.     }
  1103.  
  1104.     if (!bError && ipBindings != "*")
  1105.     {
  1106.         BOOL bError = FALSE;
  1107.         CStdString str = _T("Failed to bind the admin interface to the following IPs:");
  1108.         if (ipBindings != "")
  1109.             ipBindings += " ";
  1110.         while (ipBindings != "")
  1111.         {
  1112.             int pos = ipBindings.Find(" ");
  1113.             if (pos == -1)
  1114.                 break;
  1115.             CStdString ip = ipBindings.Left(pos);
  1116.             ipBindings = ipBindings.Mid(pos+1);
  1117.             CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface);
  1118.             if (!pAdminListenSocket->Create(nAdminPort, SOCK_STREAM, FD_ACCEPT, ip) || !pAdminListenSocket->Listen())
  1119.             {
  1120.                 delete pAdminListenSocket;
  1121.                 bError = TRUE;
  1122.                 str += _T("\n") + ip;
  1123.             }
  1124.             else
  1125.                 m_AdminListenSocketList.push_back(pAdminListenSocket);
  1126.         }
  1127.         if (bError)
  1128.             MessageBox(0, str, _T("FileZilla Server Error"), MB_ICONEXCLAMATION | MB_SERVICE_NOTIFICATION);
  1129.     }
  1130.     return !m_AdminListenSocketList.empty();
  1131. }
  1132.  
  1133. BOOL CServer::CreateListenSocket()
  1134. {
  1135.     CStdString ports = (m_pOptions ? m_pOptions->GetOption(OPTION_SERVERPORT) : "21");
  1136.     ports += " ";
  1137.     int pos = ports.Find(" ");
  1138.     bool ssl = false;
  1139.     while (pos > 0)
  1140.     {
  1141.         CStdString ipBindings = (m_pOptions ? m_pOptions->GetOption(OPTION_IPBINDINGS) : "*");
  1142.         if (ipBindings == "")
  1143.             ipBindings = "*";
  1144.         int nPort = atoi(ports.Left(pos));
  1145.         ports = ports.Mid(pos + 1);
  1146.         pos = ports.Find(" ");
  1147.  
  1148.         CStdString str;
  1149.         str.Format("Creating listen socket on port %d...", nPort);
  1150.         ShowStatus(str, 0);
  1151.         if (ipBindings == "*")
  1152.         {
  1153.             CListenSocket *pListenSocket = new CListenSocket(this, ssl);
  1154.             pListenSocket->m_pThreadList = &m_ThreadArray;
  1155.     
  1156.             if (!pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, NULL) || !pListenSocket->Listen())
  1157.             {
  1158.                 delete pListenSocket;
  1159.                 pListenSocket = NULL;
  1160.                 str.Format(_T("Failed to create listen socket on port %d"), nPort);
  1161.                 ShowStatus(str, 1);
  1162.             }
  1163.             else
  1164.                 m_ListenSocketList.push_back(pListenSocket);
  1165.         }
  1166.     
  1167.         if (ipBindings != "*")
  1168.         {
  1169.             BOOL bError = FALSE;
  1170.             CStdString str;
  1171.             str.Format(_T("Failed to bind the listen socket on port %d to the following IPs:"), nPort);
  1172.             ipBindings += " ";
  1173.             while (ipBindings != "")
  1174.             {
  1175.                 int pos = ipBindings.Find(" ");
  1176.                 if (pos == -1)
  1177.                     break;
  1178.                 CStdString ip = ipBindings.Left(pos);
  1179.                 ipBindings = ipBindings.Mid(pos + 1);
  1180.                 CListenSocket *pListenSocket = new CListenSocket(this, ssl);
  1181.                 pListenSocket->m_pThreadList = &m_ThreadArray;    
  1182.                 if (!pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, ip) || !pListenSocket->Listen())
  1183.                 {
  1184.                     delete pListenSocket;
  1185.                     bError = TRUE;
  1186.                     str += _T(" ") + ip;
  1187.                 }
  1188.                 else
  1189.                     m_ListenSocketList.push_back(pListenSocket);
  1190.             }
  1191.             if (bError)
  1192.                 ShowStatus(str, 1);
  1193.         }
  1194.  
  1195.         if (pos < 1 && !ssl && m_pOptions && m_pOptions->GetOptionVal(OPTION_ENABLESSL))
  1196.         {
  1197.             // Now create the ssl ports
  1198.             ports = (m_pOptions ? m_pOptions->GetOption(OPTION_SSLPORTS) : "990");
  1199.             ports += " ";
  1200.             pos = ports.Find(" ");
  1201.             ssl = true;
  1202.         }
  1203.     }
  1204.  
  1205.     return !m_ListenSocketList.empty();
  1206. }
  1207.  
  1208. unsigned int CServer::GetNextThreadNotificationID()
  1209. {
  1210.     for (unsigned int i = 0; i < m_ThreadNotificationIDs.size(); i++)
  1211.         if (!m_ThreadNotificationIDs[i])
  1212.             return i;
  1213.  
  1214.     m_ThreadNotificationIDs.push_back(0);
  1215.     return m_ThreadNotificationIDs.size() - 1;
  1216. }
  1217.  
  1218. void CServer::FreeThreadNotificationID(CServerThread *pThread)
  1219. {
  1220.     for (unsigned int i = 0; i < m_ThreadNotificationIDs.size(); i++)
  1221.         if (m_ThreadNotificationIDs[i] == pThread)
  1222.         {
  1223.             m_ThreadNotificationIDs[i] = 0;
  1224.             break;
  1225.         }
  1226.  
  1227. }
  1228.  
  1229. void CServer::SendState()
  1230. {
  1231.     if (!m_pAdminInterface)
  1232.         return;
  1233.  
  1234.     // Send state to interface
  1235.     unsigned char buffer[2];
  1236.     buffer[0] = m_nServerState / 256;
  1237.     buffer[1] = m_nServerState % 256;
  1238.     m_pAdminInterface->SendCommand(2, 2, buffer, 2);
  1239. }
  1240.