bool CServer::Create() { //Create window WNDCLASSEX wndclass{}; wndclass.cbSize = sizeof wndclass; wndclass.lpfnWndProc = WindowProc; wndclass.hInstance = GetModuleHandle(0); wndclass.lpszClassName = _T("FileZilla Server Helper Window"); RegisterClassEx(&wndclass); m_hWnd = CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0)); if (!m_hWnd) return false; SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this); hMainWnd = m_hWnd; m_pOptions = new COptions; m_pFileLogger = new CFileLogger(m_pOptions); m_pAutoBanManager = new CAutoBanManager(m_pOptions); //Create the threads int num = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM); for (int i = 0; i < num; ++i) { int index = GetNextThreadNotificationID(); CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index); m_ThreadNotificationIDs[index] = pThread; if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { pThread->ResumeThread(); m_ThreadArray.push_back(pThread); } } m_pFileLogger->Log(GetProductVersionString() + _T(" started")); m_pFileLogger->Log(_T("Initializing Server.")); m_nTimerID = SetTimer(m_hWnd, 1234, 10000, NULL); ASSERT(m_nTimerID); m_nBanTimerID = SetTimer(m_hWnd, 1235, 60000, NULL); ASSERT(m_nBanTimerID); if (CreateListenSocket()) { m_nServerState = STATE_ONLINE; ShowStatus(_T("Server online."), 0); } else ShowStatus(_T("Server not online."), 1); CreateAdminListenSocket(); m_sslLoader = make_unique<CAsyncSslSocketLayer>(0); m_sslLoader->InitSSL(); return true; }
bool CServer::ToggleActive(int nServerState) { if (nServerState & STATE_MASK_GOOFFLINE) { if (m_nServerState & STATE_MASK_GOOFFLINE) return false; int ftm_gooffline_arg{}; switch (nServerState & STATE_MASK_GOOFFLINE) { case STATE_GOOFFLINE_LOGOUT: ftm_gooffline_arg = 2; break; case STATE_GOOFFLINE_WAITTRANSFER: ftm_gooffline_arg = 1; break; case STATE_GOOFFLINE_NOW: ftm_gooffline_arg = 0; break; default: return false; } for (auto & listenSocket : m_ListenSocketList) { listenSocket->Close(); delete listenSocket; } m_ListenSocketList.clear(); std::move(m_ThreadArray.begin(), m_ThreadArray.end(), std::back_inserter(m_ClosedThreads)); m_ThreadArray.clear(); for (auto & closedThread : m_ClosedThreads) { closedThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, ftm_gooffline_arg); } m_nServerState &= ~STATE_ONLINE; if (!m_ClosedThreads.empty()) { m_nServerState |= nServerState & STATE_MASK_GOOFFLINE; } } else if (nServerState & STATE_ONLINE) { if (m_ListenSocketList.empty()) { if (!CreateListenSocket()) { ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1); return true; } } if (!m_ListenSocketList.empty()) { ShowStatus(_T("Server online"), 0); int num = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_THREADNUM) : 2); //Recreate the threads while (m_ThreadArray.size() < num) { int index = GetNextThreadNotificationID(); CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index); m_ThreadNotificationIDs[index] = pThread; if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { m_ThreadArray.push_back(pThread); pThread->ResumeThread(); } } } for (auto iter = m_ListenSocketList.begin(); iter != m_ListenSocketList.end(); ++iter) (*iter)->m_bLocked = nServerState & STATE_LOCKED; // Set closing threads to "wait until logout" mode. for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); ++iter) (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2); m_nServerState = (m_ListenSocketList.empty() ? 0 : STATE_ONLINE) | (nServerState & STATE_LOCKED); } SendState(); return true; }
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength) { switch (nID) { case 2: if (!nDataLength) { unsigned char buffer[2]; buffer[0] = m_nServerState / 256; buffer[1] = m_nServerState % 256; pAdminSocket->SendCommand(1, 2, buffer, 2); } else if (nDataLength == 2) { ToggleActive(*pData * 256 + pData[1]); unsigned char buffer[2]; buffer[0] = m_nServerState / 256; buffer[1] = m_nServerState % 256; pAdminSocket->SendCommand(1, 2, buffer, 2); } else pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1); break; case 3: if (!nDataLength) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1); } else if (*pData == USERCONTROL_GETLIST) { int len = 4; std::map<int, t_connectiondata>::iterator iter; for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) { const t_connectiondata& data = iter->second; auto ip = ConvToNetwork(data.ip); auto user = ConvToNetwork(data.user); len += 4 + ip.size() + 2 + 4 + user.size() + 2 + 1; if (data.transferMode) { auto physicalFile = ConvToNetwork(data.physicalFile); auto logicalFile = ConvToNetwork(data.logicalFile); len += 2 + physicalFile.size() + 2 + logicalFile.size(); if (data.currentOffset != 0) len += 8; if (data.totalSize != -1) len += 8; } } unsigned char *buffer = new unsigned char[len]; buffer[0] = USERCONTROL_GETLIST; buffer[1] = ((m_UsersList.size() / 256) / 256) & 0xff; buffer[2] = (m_UsersList.size() / 256) & 0xff; buffer[3] = m_UsersList.size() % 256; unsigned char *p = buffer + 4; for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) { const t_connectiondata& data = iter->second; auto ip = ConvToNetwork(data.ip); auto user = ConvToNetwork(data.user); memcpy(p, &data.userid, 4); p += 4; *p++ = (ip.size() / 256) & 0xff; *p++ = ip.size() % 256; memcpy(p, ip.c_str(), ip.size()); p += ip.size(); memcpy(p, &data.port, 4); p += 4; *p++ = (user.size() / 256) & 0xff; *p++ = user.size() % 256; memcpy(p, user.c_str(), user.size()); p += user.size(); *p = data.transferMode; if (data.transferMode) { // Bit 5 and 6 indicate presence of currentOffset and totalSize. if (data.currentOffset != 0) { *p |= 0x20; } if (data.totalSize != -1) { *p |= 0x40; } p++; auto physicalFile = ConvToNetwork(data.physicalFile); *p++ = (physicalFile.size() / 256) & 0xff; *p++ = physicalFile.size() % 256; memcpy(p, physicalFile.c_str(), physicalFile.size()); p += physicalFile.size(); auto logicalFile = ConvToNetwork(data.logicalFile); *p++ = (logicalFile.size() / 256) & 0xff; *p++ = logicalFile.size() % 256; memcpy(p, logicalFile.c_str(), logicalFile.size()); p += logicalFile.size(); if (data.currentOffset != 0) { memcpy(p, &data.currentOffset, 8); p += 8; } if (data.totalSize != -1) { memcpy(p, &data.totalSize, 8); p += 8; } } else { p++; } } m_pAdminInterface->SendCommand(1, 3, buffer, len); delete [] buffer; } else if (*pData == USERCONTROL_KICK || *pData == USERCONTROL_BAN) { if (nDataLength != 5) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { int nUserID; memcpy(&nUserID, pData+1, 4); std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID); if (iter!=m_UsersList.end()) { if (*pData == USERCONTROL_BAN) { // Get the list of IP filter rules. CStdString ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED); if (ips != _T("")) ips += _T(" "); int pos = ips.Find(' '); while (pos != -1) { CStdString blockedIP = ips.Left(pos); ips = ips.Mid(pos + 1); pos = ips.Find(' '); if (MatchesFilter(blockedIP, iter->second.ip)) break; } if (pos == -1) { ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED); if (ips != _T("")) ips += _T(" "); ips += iter->second.ip; m_pOptions->SetOption(OPTION_IPFILTER_DISALLOWED, ips); } } t_controlmessage *msg = new t_controlmessage; msg->command = USERCONTROL_KICK; msg->socketid = nUserID; iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg); char buffer[2]; buffer[0] = *pData; buffer[1] = 0; pAdminSocket->SendCommand(1, 3, &buffer, 2); } else { char buffer[2]; buffer[0] = USERCONTROL_KICK; buffer[1] = 1; pAdminSocket->SendCommand(1, 3, &buffer, 2); } } } else pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data")+1); break; case 5: if (!nDataLength) { unsigned char *pBuffer = NULL; DWORD nBufferLength = 0; if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength)) { pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength); delete [] pBuffer; } } else if (m_pOptions) { if (nDataLength < 2) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { CStdString const listenPorts = m_pOptions->GetOption(OPTION_SERVERPORT); CStdString const listenPortsSsl = m_pOptions->GetOption(OPTION_TLSPORTS); bool const enableSsl = m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0; CStdString const ipBindings = m_pOptions->GetOption(OPTION_IPBINDINGS); int const nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT); CStdString const adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS); CStdString peerIP; UINT port = 0; bool bLocal = false; if (!pAdminSocket->GetPeerName(peerIP, port)) return FALSE; else bLocal = IsLocalhost(peerIP); if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal)) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1); char buffer = 1; pAdminSocket->SendCommand(1, 5, &buffer, 1); break; } char buffer = 0; pAdminSocket->SendCommand(1, 5, &buffer, 1); unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM); if (m_nServerState & STATE_ONLINE) { if (threadnum > m_ThreadArray.size()) { while (threadnum > m_ThreadArray.size()) { int index = GetNextThreadNotificationID(); CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index); m_ThreadNotificationIDs[index] = pThread; if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { pThread->ResumeThread(); m_ThreadArray.push_back(pThread); } } CStdString str; str.Format(_T("Number of threads increased to %d."), threadnum); ShowStatus(str, 0); } else if (threadnum < m_ThreadArray.size()) { CStdString str; str.Format(_T("Decreasing number of threads to %d."), threadnum); ShowStatus(str, 0); unsigned int i = 0; std::vector<CServerThread *> newList; for (auto iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++, i++) { if (i >= threadnum) { (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2); m_ClosedThreads.push_back(*iter); } else newList.push_back(*iter); } m_ThreadArray.swap(newList); } } if (listenPorts != m_pOptions->GetOption(OPTION_SERVERPORT) || enableSsl != (m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0) || (m_pOptions->GetOptionVal(OPTION_ENABLETLS) && listenPortsSsl != m_pOptions->GetOption(OPTION_TLSPORTS)) || ipBindings != m_pOptions->GetOption(OPTION_IPBINDINGS)) { if (!m_ListenSocketList.empty()) { ShowStatus(_T("Closing all listening sockets"), 0); for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); ++listIter) { (*listIter)->Close(); delete *listIter; } m_ListenSocketList.clear(); if (!CreateListenSocket()) { ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1); m_nServerState &= ~STATE_ONLINE; } else { ShowStatus(_T("Listen socket port changed"), 0); if (!(m_nServerState & STATE_MASK_GOOFFLINE)) m_nServerState |= STATE_ONLINE; } SendState(); } } if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings != m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)) { CreateAdminListenSocket(); } VerifyTlsSettings(pAdminSocket); VerifyPassiveModeSettings(pAdminSocket); } } break; case 6: if (!nDataLength) { unsigned char *pBuffer = NULL; DWORD nBufferLength = 0; CPermissions permissions = CPermissions(std::function<void()>()); permissions.GetAsCommand(&pBuffer, &nBufferLength); pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength); delete [] pBuffer; } else { if (nDataLength < 2) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { CPermissions permissions = CPermissions(std::function<void()>()); if (!permissions.ParseUsersCommand(pData, nDataLength)) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1); char buffer = 1; pAdminSocket->SendCommand(1, 6, &buffer, 1); break; } char buffer = 0; pAdminSocket->SendCommand(1, 6, &buffer, 1); } } break; case 8: pAdminSocket->SendCommand(1, 8, NULL, 0); break; default: { CStdStringA str; str.Format("\001Protocol error: Unknown command (%d).", nID); pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength()); } break; } return TRUE; }
bool CServer::Create() { //Create window WNDCLASSEX wndclass; wndclass.cbSize=sizeof wndclass; wndclass.style=0; wndclass.lpfnWndProc=WindowProc; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hInstance=GetModuleHandle(0); wndclass.hIcon=0; wndclass.hCursor=0; wndclass.hbrBackground=0; wndclass.lpszMenuName=0; wndclass.lpszClassName=_T("FileZilla Server Helper Window"); wndclass.hIconSm=0; RegisterClassEx(&wndclass); m_hWnd=CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0)); if (!m_hWnd) return false; SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this); hMainWnd = m_hWnd; m_pOptions=new COptions; m_pFileLogger = new CFileLogger(m_pOptions); //Create the threads int num = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM); for (int i=0;i<num;i++) { CServerThread *pThread = new CServerThread; if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { pThread->ResumeThread(); m_ThreadArray.push_back(pThread); } } m_pFileLogger->Log(GetVersionString() + " started"); m_pFileLogger->Log("Initializing Server."); m_pListenSocket = new CListenSocket(this); m_pListenSocket->m_pThreadList = &m_ThreadArray; //TODO Start on startup check int nPort = (int)m_pOptions->GetOptionVal(OPTION_SERVERPORT); CStdString str; str.Format("Creating listen socket on port %d...", nPort); ShowStatus(str, 0); if (!m_pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, 0) || !m_pListenSocket->Listen()) { str.Format("Failed to create listen socket on port %d. Server is not online!", nPort); ShowStatus(str, 1); delete m_pListenSocket; m_pListenSocket = NULL; } else { str.Format("Server online."); ShowStatus(str, 0); m_nServerState = 1; } m_nTimerID = SetTimer(m_hWnd, 1234, 10000, NULL); ASSERT(m_nTimerID); CreateAdminListenSocket(); return true; }
BOOL CServer::ToggleActive(int nServerState) { if (nServerState&2) { if (m_pListenSocket) { m_pListenSocket->Close(); delete m_pListenSocket; m_pListenSocket = NULL; } for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++) (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0); if (m_nServerState & 1) m_nServerState = m_nServerState |= 2; } else if (nServerState&4) { if (m_pListenSocket) { m_pListenSocket->Close(); delete m_pListenSocket; m_pListenSocket = NULL; } for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++) (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2); if (m_nServerState & 1) m_nServerState = m_nServerState |= 4; } else if (nServerState&8) { if (m_pListenSocket) { m_pListenSocket->Close(); delete m_pListenSocket; m_pListenSocket = NULL; } for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++) (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 1); if (m_nServerState & 1) m_nServerState = m_nServerState |= 8; } else if (nServerState&1) { if (!m_pListenSocket) { m_pListenSocket = new CListenSocket(this); m_pListenSocket->m_pThreadList=&m_ThreadArray; int nPort = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_SERVERPORT) : 21); CStdString str; str.Format("Creating listen socket on port %d...", nPort); ShowStatus(str, 0); if (!m_pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, 0) || !m_pListenSocket->Listen()) { delete m_pListenSocket; m_pListenSocket = NULL; str.Format("Failed to create listen socket on port %d. Server is not online!", nPort); ShowStatus(str, 1); } else { ShowStatus(_T("Server online"), 0); } } if (m_pListenSocket) { int i=0; int num = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_THREADNUM) : 2); for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++, i++) if (i<num) (*iter)->DontQuit(); else break; //Recreate the threads for (i=m_ThreadArray.size();i<num;i++) { CServerThread *pThread = new CServerThread; if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { pThread->ResumeThread(); m_ThreadArray.push_back(pThread); } } } m_pListenSocket->m_bLocked = nServerState & 0x10; m_nServerState = (m_pListenSocket?1:0) + (nServerState&16); } unsigned char buffer[2]; buffer[0]=m_nServerState/256; buffer[1]=m_nServerState%256; m_pAdminInterface->SendCommand(2, 2, buffer, 2); return TRUE; }
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength) { switch (nID) { case 2: if (!nDataLength) { unsigned char buffer[2]; buffer[0]=m_nServerState/256; buffer[1]=m_nServerState%256; pAdminSocket->SendCommand(1, 2, buffer, 2); } else if (nDataLength == 2) { ToggleActive(*pData*256+pData[1]); unsigned char buffer[2]; buffer[0]=m_nServerState/256; buffer[1]=m_nServerState%256; pAdminSocket->SendCommand(1, 2, buffer, 2); } else pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); break; case 3: if (!nDataLength) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else if (*pData == USERCONTROL_GETLIST) { int len = 3; std::map<int, t_connectiondata>::iterator iter; for (iter=m_UsersList.begin(); iter!=m_UsersList.end(); iter++) len += 4 + strlen(iter->second.ip)+2 + 4 + strlen(iter->second.user)+2; unsigned char *buffer = new unsigned char[len]; buffer[0] = USERCONTROL_GETLIST; buffer[1] = m_UsersList.size() / 256; buffer[2] = m_UsersList.size() % 256; unsigned char *p = buffer + 3; for (iter=m_UsersList.begin(); iter!=m_UsersList.end(); iter++) { USES_CONVERSION; memcpy(p, &iter->second.userid, 4); p+=4; *p++ = strlen(iter->second.ip) / 256; *p++ = strlen(iter->second.ip) % 256; memcpy(p, T2CA(iter->second.ip), strlen(T2CA(iter->second.ip))); p+=strlen(T2CA(iter->second.ip)); memcpy(p, &iter->second.port, 4); p+=4; if (iter->second.user) { *p++ = strlen(iter->second.user) / 256; *p++ = strlen(iter->second.user) % 256; memcpy(p, T2CA(iter->second.user), strlen(T2CA(iter->second.user))); p+=strlen(T2CA(iter->second.user)); } else { *p++ = 0; *p++ = 0; } } m_pAdminInterface->SendCommand(1, 3, buffer, len); delete [] buffer; } else if (*pData == USERCONTROL_KICK) { if (nDataLength != 5) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { int nUserID; memcpy(&nUserID, pData+1, 4); std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID); if (iter!=m_UsersList.end()) { t_controlmessage *msg=new t_controlmessage; msg->command=USERCONTROL_KICK; msg->socketid=nUserID; iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg); char buffer[2]; buffer[0] = USERCONTROL_KICK; buffer[1] = 0; pAdminSocket->SendCommand(1, 3, &buffer, 2); } else { char buffer[2]; buffer[0] = USERCONTROL_KICK; buffer[1] = 1; pAdminSocket->SendCommand(1, 3, &buffer, 2); } } } else pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data")+1); break; case 5: if (!nDataLength) { char *pBuffer = NULL; DWORD nBufferLength = 0; if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength)) { pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength); delete [] pBuffer; } } else if (m_pOptions) { if (nDataLength < 2) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { int nListenPort = (int)m_pOptions->GetOptionVal(OPTION_SERVERPORT); int nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT); CStdString adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS); SOCKADDR_IN sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); int nSockAddrLen = sizeof(sockAddr); BOOL bLocal = pAdminSocket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen) && sockAddr.sin_addr.S_un.S_addr == 0x0100007f; if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal)) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1); char buffer = 1; pAdminSocket->SendCommand(1, 5, &buffer, 1); break; } char buffer = 0; pAdminSocket->SendCommand(1, 5, &buffer, 1); unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM); if (threadnum>m_ThreadArray.size()) { int newthreads=threadnum-m_ThreadArray.size(); for (int i=0;i<newthreads;i++) { CServerThread *pThread = new CServerThread; if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { pThread->ResumeThread(); m_ThreadArray.push_back(pThread); } } CStdString str; str.Format("Number of threads increased to %d.", threadnum); ShowStatus(str, 0); } else if (threadnum<m_ThreadArray.size()) { CStdString str; str.Format("Decreasing number of threads to %d.", threadnum); ShowStatus(str, 0); unsigned int i=0; for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++,i++) if (i>=threadnum) (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2); } if (nListenPort != m_pOptions->GetOptionVal(OPTION_SERVERPORT)) { if (m_pListenSocket) { CStdString str; str.Format("Closing listen socket on port %d", nListenPort); ShowStatus(str, 0); m_pListenSocket->Close(); str.Format("Creating listen socket on port %I64d...", m_pOptions->GetOptionVal(OPTION_SERVERPORT)); ShowStatus(str, 0); if (!m_pListenSocket->Create((int)m_pOptions->GetOptionVal(OPTION_SERVERPORT), SOCK_STREAM,FD_ACCEPT,0) || !m_pListenSocket->Listen()) { delete m_pListenSocket; m_pListenSocket = NULL; str.Format("Failed to create listen socket on port %I64d. Server is not online!", m_pOptions->GetOptionVal(OPTION_SERVERPORT)); ShowStatus(str,1); m_nServerState = 0; } else ShowStatus("Listen socket port changed",0); } } if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings!=m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)) { if (nAdminListenPort == m_pOptions->GetOptionVal(OPTION_ADMINPORT)) { for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++) { (*iter)->Close(); delete *iter; } m_AdminListenSocketList.clear(); } CAdminListenSocket *pSocket = new CAdminListenSocket(m_pAdminInterface); if (!pSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)!="*") ? _T("127.0.0.1") : NULL)) { delete pSocket; CStdString str; str.Format(_T("Failed to change admin listen port to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT)); m_pOptions->SetOption(OPTION_ADMINPORT, nAdminListenPort); ShowStatus(str, 1); } else { pSocket->Listen(); for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++) { (*iter)->Close(); delete *iter; } m_AdminListenSocketList.clear(); m_AdminListenSocketList.push_back(pSocket); if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT)) { CStdString str; str.Format(_T("Admin listen port changed to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT)); ShowStatus(str, 0); } if (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS) != "*") { BOOL bError = FALSE; CStdString str = _T("Failed to bind the admin interface to the following IPs:"); CStdString ipBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS); if (ipBindings != "") ipBindings += " "; while (ipBindings != "") { int pos = ipBindings.Find(" "); if (pos == -1) break; CStdString ip = ipBindings.Left(pos); ipBindings = ipBindings.Mid(pos+1); CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface); if (!pAdminListenSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, ip) || !pAdminListenSocket->Listen()) { bError = TRUE; str += _T(" ") + ip; delete pAdminListenSocket; } else m_AdminListenSocketList.push_back(pAdminListenSocket); } if (bError) ShowStatus(str, 1); } if (adminIpBindings!=m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)) ShowStatus(_T("Admin interface IP bindings changed"), 0); } } } } break; case 6: if (!nDataLength) { char *pBuffer = NULL; DWORD nBufferLength = 0; CPermissions permissions; permissions.GetAsCommand(&pBuffer, &nBufferLength); pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength); delete [] pBuffer; } else { if (nDataLength < 2) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { CPermissions permissions; if (!permissions.ParseUsersCommand(pData, nDataLength)) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1); char buffer = 1; pAdminSocket->SendCommand(1, 6, &buffer, 1); break; } char buffer = 0; pAdminSocket->SendCommand(1, 6, &buffer, 1); } } break; case 8: pAdminSocket->SendCommand(1, 8, NULL, 0); break; default: { CStdString str; str.Format("\001Protocol error: Unknown command (%d).", nID); pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength()); } break; } return TRUE; }