Esempio n. 1
0
BOOL CUsersDlgGeneral::SaveUser(t_user & user)
{
	user.nEnabled = m_nEnabled;
	if (!m_bNeedpass)
		user.password = _T("");
	else if (m_cPass.GetModify() && m_Pass != _T("")) {
		user.generateSalt();
		
		auto saltedPassword = ConvToNetwork(m_Pass + user.salt);

		CAsyncSslSocketLayer ssl(0);
		user.password = ConvFromNetwork(ssl.SHA512(reinterpret_cast<unsigned char const*>(saltedPassword.c_str()), saltedPassword.size()).c_str());
		if (user.password.IsEmpty()) {
			// Something went very wrong, disable user.
			user.nEnabled = false;
		}
	}

	user.nBypassUserLimit = m_nMaxUsersBypass;
	user.nUserLimit = _ttoi(m_MaxConnCount);
	user.nIpLimit = _ttoi(m_IpLimit);
	if (m_cGroup.GetCurSel()<=0)
		user.group = _T("");
	else
		m_cGroup.GetLBText(m_cGroup.GetCurSel(), user.group);

	user.comment = m_Comments;

	user.forceSsl = m_nForceSsl;

	return TRUE;
}
Esempio n. 2
0
void CServer::ShowStatus(DWORD eventDateHigh, DWORD eventDateLow, LPCTSTR msg, int nType)
{
	auto utf8 = ConvToNetwork(msg);
	if (utf8.empty())
		return;

	char *pBuffer = new char[utf8.size() + 1 + 8];
	*pBuffer = nType;
	memcpy(pBuffer + 1, &eventDateHigh, 4);
	memcpy(pBuffer + 5, &eventDateLow, 4);
	memcpy(pBuffer + 1 + 8, utf8.c_str(), utf8.size());
	if (m_pAdminInterface)
		m_pAdminInterface->SendCommand(2, 4, pBuffer, utf8.size() + 1 + 8);
	delete [] pBuffer;

	//Log string
	if (m_pFileLogger) {
		FILETIME fFileTime;
		SYSTEMTIME sFileTime;
		fFileTime.dwHighDateTime = eventDateHigh;
		fFileTime.dwLowDateTime = eventDateLow;
		if (!FileTimeToSystemTime(&fFileTime, &sFileTime)) {
			return;
		}
		TCHAR text[80];
		if (!GetDateFormat(
			LOCALE_USER_DEFAULT,			// locale for which date is to be formatted
			DATE_SHORTDATE,					// flags specifying function options
			&sFileTime,						// date to be formatted
			0,								// date format string
			text,							// buffer for storing formatted string
			80								// size of buffer
			))
			return;

		CStdString text2 = _T(" ");
		text2 += text;

		if (!GetTimeFormat(
			LOCALE_USER_DEFAULT,			// locale for which date is to be formatted
			TIME_FORCE24HOURFORMAT,			// flags specifying function options
			&sFileTime,						// date to be formatted
			0,								// date format string
			text,							// buffer for storing formatted string
			80								// size of buffer
			))
			return;

		text2 += _T(" ");
		text2 += text;
		CStdString str = msg;
		int pos = str.Find(_T("-"));
		if (pos!=-1)
		{
			str.Insert(pos, text2 + _T(" "));
		}
		m_pFileLogger->Log(str);
	}
}
Esempio n. 3
0
void COptions::SaveOptions()
{
	USES_CONVERSION;
	CStdString xmlFileName = GetExecutableDirectory() + _T("FileZilla Server.xml");
	char* bufferA = T2A(xmlFileName);
	if (!bufferA)
		return;

	TiXmlDocument document;
	if (!document.LoadFile(bufferA))
		return;

	TiXmlElement* pRoot = document.FirstChildElement("FileZillaServer");
	if (!pRoot)
		return;

	TiXmlElement* pSettings;
	while ((pSettings = pRoot->FirstChildElement("Settings")))
		pRoot->RemoveChild(pSettings);
	pSettings = pRoot->LinkEndChild(new TiXmlElement("Settings"))->ToElement();

	for (unsigned int i = 0; i < OPTIONS_NUM; i++)
	{
		if (!m_OptionsCache[i].bCached)
			continue;

		CStdString valuestr;
		if (!m_OptionsCache[i].nType)
			valuestr = m_OptionsCache[i].str;
		else
			valuestr.Format( _T("%I64d"), m_OptionsCache[i].value);

		TiXmlElement* pItem = pSettings->LinkEndChild(new TiXmlElement("Item"))->ToElement();
		pItem->SetAttribute("name", ConvToNetwork(m_Options[i].name).c_str());
		if (!m_OptionsCache[i].nType)
			pItem->SetAttribute("type", "string");
		else
			pItem->SetAttribute("type", "numeric");
		pItem->LinkEndChild(new TiXmlText(ConvToNetwork(valuestr).c_str()));
	}

	SaveSpeedLimits(pSettings);

	document.SaveFile(bufferA);
}
Esempio n. 4
0
BOOL CFileLogger::Log(LPCTSTR msg)
{
	if (m_hLogFile==INVALID_HANDLE_VALUE)
		return TRUE;

	auto utf8 = ConvToNetwork(msg);
	if (utf8.empty())
		return FALSE;

	DWORD numwritten;
	if (!WriteFile(m_hLogFile, utf8.c_str(), utf8.size(), &numwritten, 0) || !WriteFile(m_hLogFile, "\r\n", 2, &numwritten, 0))
	{
		CloseHandle(m_hLogFile);
		m_hLogFile = INVALID_HANDLE_VALUE;
		return FALSE;
	}

	return TRUE;
}
Esempio n. 5
0
BOOL CAdminSocket::SendCommand(LPCTSTR pszCommand, int nTextType)
{
	std::string utf8;
	if (pszCommand)
		utf8 = ConvToNetwork(pszCommand);

	DWORD nDataLength = utf8.size() + 1;

	t_data data(nDataLength + 5);
	*data.pData = 2;
	*data.pData |= 1 << 2;
	memcpy(&*data.pData + 1, &nDataLength, 4);
	*(&*data.pData+5) = nTextType;
	memcpy(reinterpret_cast<char *>(&*data.pData+6), utf8.c_str(), nDataLength - 1);

	m_SendBuffer.push_back(data);

	return SendPendingData();
}
BOOL CUsersDlgGeneral::SaveUser(t_user *pUser)
{
	if (!pUser)
		return FALSE;
	
	pUser->nEnabled = m_nEnabled;
	pUser->password = m_Pass;
	if (!m_bNeedpass)
		pUser->password = _T("");
	else if (m_cPass.GetModify() && m_Pass != _T(""))
	{
		char *tmp = ConvToNetwork(pUser->password);
		if (!tmp)
		{
			tmp = new char[1];
			*tmp = 0;
		}
		MD5 md5;
		md5.update((unsigned char *)tmp, strlen(tmp));
		delete [] tmp;
		md5.finalize();
		char *res = md5.hex_digest();
		CString hash = res;
		delete [] res;
		pUser->password = hash;	
	}
	
	pUser->nBypassUserLimit = m_nMaxUsersBypass;
	pUser->nUserLimit = _ttoi(m_MaxConnCount);
	pUser->nIpLimit = _ttoi(m_IpLimit);
	if (m_cGroup.GetCurSel()<=0)
		pUser->group = _T("");
	else
		m_cGroup.GetLBText(m_cGroup.GetCurSel(), pUser->group);

	pUser->comment = m_Comments;

	pUser->forceSsl = m_nForceSsl;
	
	return TRUE;
}
Esempio n. 7
0
BOOL CFileLogger::Log(LPCTSTR msg)
{
	if (m_hLogFile==INVALID_HANDLE_VALUE)
		return TRUE;

	char* utf8 = ConvToNetwork(msg);
	if (!utf8)
		return FALSE;

	DWORD numwritten;
	if (!WriteFile(m_hLogFile, utf8, strlen(utf8), &numwritten, 0) || !WriteFile(m_hLogFile, "\r\n", 2, &numwritten, 0))
	{
		delete [] utf8;
		CloseHandle(m_hLogFile);
		m_hLogFile = INVALID_HANDLE_VALUE;
		return FALSE;
	}
	delete [] utf8;

	return TRUE;
}
Esempio n. 8
0
void CServer::ShowStatus(LPCTSTR msg, int nType, CAdminSocket* pAdminSocket)
{
	if (!msg)
		return;

	auto utf8 = ConvToNetwork(msg);
	if (utf8.empty())
		return;

	char *pBuffer = new char[utf8.size() + 1];
	*pBuffer = nType;
	memcpy(pBuffer + 1, utf8.c_str(), utf8.size());
	if (pAdminSocket) {
		pAdminSocket->SendCommand(2, 1, pBuffer, utf8.size() + 1);
	}
	else if (m_pAdminInterface)
		m_pAdminInterface->SendCommand(2, 1, pBuffer, utf8.size() + 1);
	delete [] pBuffer;

	if (m_pFileLogger)
		m_pFileLogger->Log(msg);
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
LRESULT CServer::OnServerMessage(CServerThread* pThread, WPARAM wParam, LPARAM lParam)
{
	if (wParam == FSM_STATUSMESSAGE) {
		t_statusmsg *msg = reinterpret_cast<t_statusmsg *>(lParam);
		if (!msg)
			return 0;

		CStdString str;

		FILETIME fFileTime;
		SystemTimeToFileTime(&msg->time, &fFileTime);

		str.Format(_T("(%06d)- %s (%s)> %s"), msg->userid, (LPCTSTR)msg->user, (LPCTSTR)msg->ip, (LPCTSTR)msg->status);
		ShowStatus(fFileTime.dwHighDateTime, fFileTime.dwLowDateTime, str, msg->type);
		delete [] msg->status;
		delete [] msg->user;
		delete msg;
	}
	else if (wParam == FSM_CONNECTIONDATA) {
		t_connop *pConnOp = reinterpret_cast<t_connop*>(lParam);
		if (!pConnOp)
			return 0;

		int len{};
		unsigned char *buffer{};

		switch (pConnOp->op) {
		case USERCONTROL_CONNOP_ADD:
			{
				t_connectiondata_add* pData = (t_connectiondata_add*)pConnOp->data;
				t_connectiondata data;
				data.userid = pConnOp->userid;
				data.pThread = pThread;
				_tcsncpy(data.ip, pData->ip, 40);
				data.port = pData->port;
				data.transferMode = 0;
				data.currentOffset = 0;
				data.totalSize = -1;

				m_UsersList[pConnOp->userid] = data;

				auto utf8 = ConvToNetwork(pData->ip);
				len = 2 + 4 + 2 + utf8.size() + 4;
				buffer = new unsigned char[len];
				buffer[2 + 4] = (utf8.size() / 256) & 0xff;
				buffer[2 + 4 + 1] = utf8.size() % 256;
				memcpy(buffer + 2 + 4 + 2, utf8.c_str(), utf8.size());
				memcpy(buffer + 2 + 4 + 2 + utf8.size(), &pData->port, 4);

				delete pData;
			}
			break;
		case USERCONTROL_CONNOP_CHANGEUSER:
			{
				t_connectiondata_changeuser* pData = (t_connectiondata_changeuser*)pConnOp->data;
				m_UsersList[pConnOp->userid].user = pData->user;

				auto utf8 = ConvToNetwork(pData->user);
				len = 2 + 4 + 2 + utf8.size();
				buffer = new unsigned char[len];
				buffer[2 + 4] = (utf8.size() / 256) & 0xff;
				buffer[2 + 4 + 1] = utf8.size() % 256;
				memcpy(buffer + 2 + 4 + 2, utf8.c_str(), utf8.size());

				delete pData;
			}
			break;
		case USERCONTROL_CONNOP_REMOVE:
			{
				std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(pConnOp->userid);
				if (iter != m_UsersList.end())
					m_UsersList.erase(iter);

				len = 6;
				buffer = new unsigned char[len];
			}
			break;
		case USERCONTROL_CONNOP_TRANSFERINIT:
			{
				t_connectiondata_transferinfo* pData = (t_connectiondata_transferinfo*)pConnOp->data;
				t_connectiondata& data = m_UsersList[pConnOp->userid];
				data.transferMode = pData->transferMode;
				data.physicalFile = pData->physicalFile;
				data.logicalFile = pData->logicalFile;
				data.currentOffset = pData->startOffset;
				data.totalSize = pData->totalSize;

				if (data.transferMode) {
					auto physicalFile = ConvToNetwork(pData->physicalFile);
					auto logicalFile = ConvToNetwork(pData->logicalFile);
					len = 2 + 4 + 1 + 2 + physicalFile.size() + 2 + logicalFile.size();
					if (data.currentOffset != 0)
						len += 8;
					if (data.totalSize != -1)
						len += 8;

					buffer = new unsigned char[len];
					unsigned char *p = buffer + 6;
					*p = 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++;

					*p++ = (physicalFile.size() / 256) & 0xff;
					*p++ = physicalFile.size() % 256;
					memcpy(p, physicalFile.c_str(), physicalFile.size());
					p += physicalFile.size();

					*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
				{
					len = 2 + 4 + 1;
					buffer = new unsigned char[len];
					buffer[2 + 4] = 0;
				}
				delete pData;
			}
			break;
		case USERCONTROL_CONNOP_TRANSFEROFFSETS:
			{
				t_connectiondata_transferoffsets* pData = (t_connectiondata_transferoffsets*)pConnOp->data;
				buffer = pData->pData;
				len = pData->len;

				unsigned char* p = buffer + 2;
				int* userid;
				__int64* offset;
				while ((p - buffer + 12) <= len)
				{
					userid = (int*)p;
					offset = (__int64*)(p + 4);
					t_connectiondata& data = m_UsersList[*userid];
					data.currentOffset = *offset;

					p += 12;
				}
				delete pData;
			}
			break;
		default:
			delete pConnOp;
			return 0;
		}
		buffer[0] = USERCONTROL_CONNOP;
		buffer[1] = pConnOp->op;
		if (pConnOp->op != USERCONTROL_CONNOP_TRANSFEROFFSETS)
			memcpy(buffer + 2, &pConnOp->userid, 4);

		m_pAdminInterface->SendCommand(2, 3, buffer, len);
		delete [] buffer;
		delete pConnOp;
	}
	else if (wParam == FSM_THREADCANQUIT) {
		for (auto iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); ++iter) {
			if (*iter == pThread) {
				HANDLE handle = pThread->m_hThread;
				pThread->PostThreadMessage(WM_QUIT, 0, 0);
				int res = WaitForSingleObject(handle, INFINITE);
				if (res == WAIT_FAILED)
					res = GetLastError();
				m_ThreadArray.erase(iter);
				FreeThreadNotificationID(pThread);
				if (!m_ThreadArray.size() && !m_ClosedThreads.size()) {
					m_nServerState &= ~(STATE_ONLINE | STATE_MASK_GOOFFLINE);
					SendState();
					if (!m_bQuit)
						ShowStatus(_T("Server offline."), 1);
					else {
						hMainWnd = 0;
						DestroyWindow(m_hWnd);
						m_hWnd = 0;
					}
				}
				return -1;
			}
		}
		for (auto iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); ++iter) {
			if (*iter == pThread) {
				HANDLE handle = pThread->m_hThread;
				pThread->PostThreadMessage(WM_QUIT, 0, 0);
				int res = WaitForSingleObject(handle, INFINITE);
				if (res == WAIT_FAILED)
					res = GetLastError();
				m_ClosedThreads.erase(iter);
				FreeThreadNotificationID(pThread);
				if (!m_ThreadArray.size() && !m_ClosedThreads.size()) {
					m_nServerState &= ~(STATE_ONLINE | STATE_MASK_GOOFFLINE);
					SendState();
					if (!m_bQuit)
						ShowStatus(_T("Server offline."), 1);
					else {
						hMainWnd = 0;
						DestroyWindow(m_hWnd);
						m_hWnd = 0;
					}
				}
				return -1;
			}

		}
	}
	else if (wParam == FSM_SEND) {
		char buffer[5];
		buffer[0] = 1;
		memcpy(buffer+1, &lParam, 4);
		m_pAdminInterface->SendCommand(2, 7, buffer, 5);
		m_nSendCount += lParam;
	}
	else if (wParam == FSM_RECV) {
		char buffer[5];
		buffer[0] = 0;
		memcpy(buffer+1, &lParam, 4);
		m_pAdminInterface->SendCommand(2, 7, buffer, 5);
		m_nRecvCount += lParam;
	}
	return 0;
}
Esempio n. 11
0
BOOL COptions::GetAsCommand(char **pBuffer, DWORD *nBufferLength)
{
	int i;
	DWORD len = 2;

	simple_lock lock(m_mutex);
	for (i=0; i<OPTIONS_NUM; ++i) {
		len+=1;
		if (!m_Options[i].nType)
		{
			len += 3;
			auto utf8 = ConvToNetwork(GetOption(i + 1));

			if ((i + 1) != OPTION_ADMINPASS)
				len += utf8.size();
			else
			{
				if (GetOption(i+1).GetLength() < 6 && utf8.size() > 0)
					len++;
			}
		}
		else
			len += 8;
	}

	len += 4;
	SPEEDLIMITSLIST::const_iterator iter;
	for (i = 0; i < 2; i++)
		for (iter = m_sSpeedLimits[i].begin(); iter != m_sSpeedLimits[i].end(); iter++)
			len += iter->GetRequiredBufferLen();

	*pBuffer=new char[len];
	char *p=*pBuffer;
	*p++ = OPTIONS_NUM / 256;
	*p++ = OPTIONS_NUM % 256;
	for (i=0; i<OPTIONS_NUM; ++i) {
		*p++ = m_Options[i].nType;
		switch(m_Options[i].nType) {
		case 0:
			{
				CStdString str = GetOption(i+1);
				if ((i+1)==OPTION_ADMINPASS) //Do NOT send admin password,
											 //instead send empty string if admin pass is set
											 //and send a single char if admin pass is invalid (len < 6)
				{
					if (str.GetLength() >= 6 || str == _T(""))
						str = _T("");
					else
						str = _T("*");
				}

				auto utf8 = ConvToNetwork(str);

				int len = utf8.size();
				*p++ = (len / 256) / 256;
				*p++ = (len / 256) % 256;
				*p++ = len % 256;
				memcpy(p, utf8.c_str(), len);
				p += len;
			}
			break;
		case 1:
			{
				_int64 value = GetOptionVal(i+1);
				memcpy(p, &value, 8);
				p+=8;
			}
			break;
		default:
			ASSERT(FALSE);
		}
	}

	for (i = 0; i < 2; ++i) {
		*p++ = m_sSpeedLimits[i].size() >> 8;
		*p++ = m_sSpeedLimits[i].size() % 256;
		for (iter = m_sSpeedLimits[i].begin(); iter != m_sSpeedLimits[i].end(); iter++)
			p = iter->FillBuffer(p);
	}

	*nBufferLength = len;

	return TRUE;
}
Esempio n. 12
0
void COptions::SetOption(int nOptionID, LPCTSTR value, bool save /*=true*/)
{
	CStdString str = value;
	Init();

	switch (nOptionID)
	{
	case OPTION_SERVERPORT:
	case OPTION_TLSPORTS:
		{
			std::set<int> portSet;

			str.TrimLeft(_T(" ,"));

			int pos = str.FindOneOf(_T(" ,"));
			while (pos != -1)
			{
				int port = _ttoi(str.Left(pos));
				if (port >= 1 && port <= 65535)
					portSet.insert(port);
				str = str.Mid(pos + 1);
				str.TrimLeft(_T(" ,"));
				pos = str.FindOneOf(_T(" ,"));
			}
			if (str != _T(""))
			{
				int port = _ttoi(str);
				if (port >= 1 && port <= 65535)
					portSet.insert(port);
			}

			str = _T("");
			for (std::set<int>::const_iterator iter = portSet.begin(); iter != portSet.end(); iter++)
			{
				CStdString tmp;
				tmp.Format(_T("%d "), *iter);
				str += tmp;
			}
			str.TrimRight(' ');
		}
		break;
	case OPTION_WELCOMEMESSAGE:
		{
			std::vector<CStdString> msgLines;
			int oldpos = 0;
			str.Replace(_T("\r\n"), _T("\n"));
			int pos = str.Find(_T("\n"));
			CStdString line;
			while (pos != -1)
			{
				if (pos)
				{
					line = str.Mid(oldpos, pos - oldpos);
					line = line.Left(CONST_WELCOMEMESSAGE_LINESIZE);
					line.TrimRight(_T(" "));
					if (msgLines.size() || line != _T(""))
						msgLines.push_back(line);
				}
				oldpos = pos + 1;
				pos = str.Find(_T("\n"), oldpos);
			}
			line = str.Mid(oldpos);
			if (line != _T(""))
			{
				line = line.Left(CONST_WELCOMEMESSAGE_LINESIZE);
				msgLines.push_back(line);
			}
			str = _T("");
			for (unsigned int i = 0; i < msgLines.size(); i++)
				str += msgLines[i] + _T("\r\n");
			str.TrimRight(_T("\r\n"));
			if (str == _T(""))
			{
				str = _T("%v");
				str += _T("\r\nwritten by Tim Kosse ([email protected])");
				str += _T("\r\nPlease visit https://filezilla-project.org/");
			}
		}
		break;
	case OPTION_ADMINIPBINDINGS:
		{
			CStdString sub;
			std::list<CStdString> ipBindList;
			for (unsigned int i = 0; i<_tcslen(value); i++)
			{
				TCHAR cur = value[i];
				if ((cur < '0' || cur > '9') && cur != '.' && cur != ':')
				{
					if (sub == _T("") && cur == '*')
					{
						ipBindList.clear();
						ipBindList.push_back(_T("*"));
						break;
					}

					if (sub != _T(""))
					{
						if (IsIpAddress(sub))
							ipBindList.push_back(sub);
						sub = _T("");
					}
				}
				else
					sub += cur;
			}
			if (sub != _T(""))
			{
				if (IsIpAddress(sub))
					ipBindList.push_back(sub);
			}
			str = _T("");
			for (std::list<CStdString>::iterator iter = ipBindList.begin(); iter!=ipBindList.end(); iter++)
				if (!IsLocalhost(*iter))
					str += *iter + _T(" ");

			str.TrimRight(_T(" "));
		}
		break;
	case OPTION_ADMINPASS:
		if (str != _T("") && str.GetLength() < 6)
			return;
		break;
	case OPTION_MODEZ_DISALLOWED_IPS:
	case OPTION_IPFILTER_ALLOWED:
	case OPTION_IPFILTER_DISALLOWED:
	case OPTION_ADMINIPADDRESSES:
		{
			str.Replace('\r', ' ');
			str.Replace('\n', ' ');
			str.Replace('\r', ' ');
			while (str.Replace(_T("  "), _T(" ")));
			str += _T(" ");

			CStdString ips;

			int pos = str.Find(' ');
			while (pos != -1)
			{
				CStdString sub = str.Left(pos);
				str = str.Mid(pos + 1);
				str.TrimLeft(' ');

				if (sub == _T("*"))
					ips += _T(" ") + sub;
				else
				{
					if (IsValidAddressFilter(sub))
						ips += " " + sub;
					pos = str.Find(' ');
				}
			}
			ips.TrimLeft(' ');

			str = ips;
		}
		break;
	case OPTION_IPBINDINGS:
		{
			std::list<CStdString> ipBindList;

			str += _T(" ");
			while (!str.empty()) {
				int pos  = str.Find(' ');
				if (pos < 0) {
					break;
				}
				CStdString sub = str.Left(pos);
				str = str.Mid(pos + 1);

				if (sub == _T("*")) {
					ipBindList.clear();
					ipBindList.push_back(_T("*"));
					break;
				}
				else if (IsIpAddress(sub, true)) {
					ipBindList.push_back(sub);
				}
			}

			if (ipBindList.empty())
				ipBindList.push_back(_T("*"));

			str.clear();
			for (auto const& ip : ipBindList) {
				str += ip + _T(" ");
			}

			str.TrimRight(_T(" "));
		}
		break;
	case OPTION_CUSTOMPASVIPSERVER:
		if (str.Find(_T("filezilla.sourceforge.net")) != -1)
			str = _T("http://ip.filezilla-project.org/ip.php");
		break;
	}

	{
		simple_lock lock(m_mutex);
		m_sOptionsCache[nOptionID-1].bCached = TRUE;
		m_sOptionsCache[nOptionID-1].nType = 0;
		m_sOptionsCache[nOptionID-1].str = str;
		m_OptionsCache[nOptionID-1]=m_sOptionsCache[nOptionID-1];
	}

	if (!save)
		return;

	USES_CONVERSION;
	CStdString xmlFileName = GetExecutableDirectory() + _T("FileZilla Server.xml");
	char* bufferA = T2A(xmlFileName);
	if (!bufferA)
		return;

	TiXmlDocument document;
	if (!document.LoadFile(bufferA))
		return;

	TiXmlElement* pRoot = document.FirstChildElement("FileZillaServer");
	if (!pRoot)
		return;

	TiXmlElement* pSettings = pRoot->FirstChildElement("Settings");
	if (!pSettings)
		pSettings = pRoot->LinkEndChild(new TiXmlElement("Settings"))->ToElement();

	TiXmlElement* pItem;
	for (pItem = pSettings->FirstChildElement("Item"); pItem; pItem = pItem->NextSiblingElement("Item"))
	{
		const char* pName = pItem->Attribute("name");
		if (!pName)
			continue;
		CStdString name(pName);
		if (name != m_Options[nOptionID-1].name)
			continue;

		break;
	}

	if (!pItem)
		pItem = pSettings->LinkEndChild(new TiXmlElement("Item"))->ToElement();
	pItem->Clear();
	pItem->SetAttribute("name", ConvToNetwork(m_Options[nOptionID - 1].name).c_str());
	pItem->SetAttribute("type", "string");
	pItem->LinkEndChild(new TiXmlText(ConvToNetwork(value).c_str()));

	document.SaveFile(bufferA);
}
Esempio n. 13
0
void COptions::SetOption(int nOptionID, _int64 value, bool save /*=true*/)
{
	switch (nOptionID)
	{
	case OPTION_MAXUSERS:
		if (value < 0)
			value = 0;
		break;
	case OPTION_THREADNUM:
		if (value < 1)
			value = 2;
		else if (value > 50)
			value = 2;
		break;
	case OPTION_TIMEOUT:
		if (value < 0)
			value = 120;
		else if (value > 9999)
			value = 120;
		break;
	case OPTION_NOTRANSFERTIMEOUT:
		if (value < 600 && value != 0)
			value = 600;
		else if (value > 9999)
			value = 600;
		break;
	case OPTION_LOGINTIMEOUT:
		if (value < 0)
			value = 60;
		else if (value > 9999)
			value = 60;
		break;
	case OPTION_ADMINPORT:
		if (value > 65535)
			value = 14147;
		else if (value < 1)
			value = 14147;
		break;
	case OPTION_LOGTYPE:
		if (value != 0 && value != 1)
			value = 0;
		break;
	case OPTION_LOGLIMITSIZE:
		if ((value > 999999 || value < 10) && value != 0)
			value = 100;
		break;
	case OPTION_LOGDELETETIME:
		if (value > 999 || value < 0)
			value = 14;
		break;
	case OPTION_DOWNLOADSPEEDLIMITTYPE:
	case OPTION_UPLOADSPEEDLIMITTYPE:
		if (value < 0 || value > 2)
			value = 0;
		break;
	case OPTION_DOWNLOADSPEEDLIMIT:
	case OPTION_UPLOADSPEEDLIMIT:
		if (value < 1)
			value = 1;
		else if (value > 1048576)
			value = 1048576;
		break;
	case OPTION_BUFFERSIZE:
		if (value < 256 || value > (1024*1024))
			value = 32768;
		break;
	case OPTION_BUFFERSIZE2:
		if (value < 256 || value > (1024*1024*128))
			value = 262144;
		break;
	case OPTION_CUSTOMPASVIPTYPE:
		if (value < 0 || value > 2)
			value = 0;
		break;
	case OPTION_MODEZ_USE:
		if (value < 0 || value > 1)
			value = 0;
		break;
	case OPTION_MODEZ_LEVELMIN:
		if (value < 0 || value > 8)
			value = 1;
		break;
	case OPTION_MODEZ_LEVELMAX:
		if (value < 8 || value > 9)
			value = 9;
		break;
	case OPTION_MODEZ_ALLOWLOCAL:
		if (value < 0 || value > 1)
			value = 0;
		break;
	case OPTION_AUTOBAN_ATTEMPTS:
		if (value < OPTION_AUTOBAN_ATTEMPTS_MIN)
			value = OPTION_AUTOBAN_ATTEMPTS_MIN;
		if (value > OPTION_AUTOBAN_ATTEMPTS_MAX)
			value = OPTION_AUTOBAN_ATTEMPTS_MAX;
		break;
	case OPTION_AUTOBAN_BANTIME:
		if (value < 1)
			value = 1;
		if (value > 999)
			value = 999;
		break;
	}

	Init();

	{
		simple_lock lock(m_mutex);
		m_sOptionsCache[nOptionID-1].nType = 1;
		m_sOptionsCache[nOptionID-1].value = value;
		m_sOptionsCache[nOptionID-1].bCached = TRUE;
		m_OptionsCache[nOptionID-1] = m_sOptionsCache[nOptionID - 1];
	}

	if (!save)
		return;

	CStdString valuestr;
	valuestr.Format( _T("%I64d"), value);

	USES_CONVERSION;
	CStdString xmlFileName = GetExecutableDirectory() + _T("FileZilla Server.xml");
	char* bufferA = T2A(xmlFileName);
	if (!bufferA)
		return;

	TiXmlDocument document;
	if (!document.LoadFile(bufferA))
		return;

	TiXmlElement* pRoot = document.FirstChildElement("FileZillaServer");
	if (!pRoot)
		return;

	TiXmlElement* pSettings = pRoot->FirstChildElement("Settings");
	if (!pSettings)
		pSettings = pRoot->LinkEndChild(new TiXmlElement("Settings"))->ToElement();

	TiXmlElement* pItem;
	for (pItem = pSettings->FirstChildElement("Item"); pItem; pItem = pItem->NextSiblingElement("Item")) {
		const char* pName = pItem->Attribute("name");
		if (!pName)
			continue;
		CStdString name(pName);
		if (name != m_Options[nOptionID-1].name)
			continue;

		break;
	}

	if (!pItem)
		pItem = pSettings->LinkEndChild(new TiXmlElement("Item"))->ToElement();
	pItem->Clear();
	pItem->SetAttribute("name", ConvToNetwork(m_Options[nOptionID-1].name).c_str());
	pItem->SetAttribute("type", "numeric");
	pItem->LinkEndChild(new TiXmlText(ConvToNetwork(valuestr).c_str()));

	document.SaveFile(bufferA);
}
Esempio n. 14
0
static void SetText(TiXmlElement* pElement, const CStdString& text)
{
	pElement->Clear();
	pElement->LinkEndChild(new TiXmlText(ConvToNetwork(text).c_str()));
}
Esempio n. 15
0
bool COptionsDlg::GetAsCommand(unsigned char **pBuffer, DWORD *nBufferLength)
{
	DWORD len = 2;
	int i;
	for (i = 0; i < OPTIONS_NUM; ++i) {
		++len;
		if (!m_Options[i].nType) {
			int strlen = ConvToNetwork(GetOption(i + 1)).size();
			if (strlen > 0xFFFFFF)
				return false;
			len += strlen;
			len += 3;
		}
		else
			len += 8;
	}
	len += 4; //Number of rules
	if (m_pOptionsSpeedLimitPage->m_DownloadSpeedLimits.size() > 0xffff || m_pOptionsSpeedLimitPage->m_UploadSpeedLimits.size() > 0xffff) {
		return false;
	}
	for (auto const& limit : m_pOptionsSpeedLimitPage->m_DownloadSpeedLimits) {
		len += limit.GetRequiredBufferLen();
	}
	for (auto const& limit : m_pOptionsSpeedLimitPage->m_UploadSpeedLimits) {
		len += limit.GetRequiredBufferLen();
	}

	*pBuffer = new unsigned char[len];
	unsigned char *p = *pBuffer;
	*p++ = OPTIONS_NUM / 256;
	*p++ = OPTIONS_NUM % 256;
	for (i = 0; i < OPTIONS_NUM; ++i) {
		*p++ = m_Options[i].nType;
		switch (m_Options[i].nType) {
		case 0:
			{
				auto utf8 = ConvToNetwork(GetOption(i + 1));
				int slen = utf8.size();
				*p++ = ((slen / 256) / 256) & 0xffu;
				*p++ = (slen / 256) & 0xffu;
				*p++ = slen % 256;
				memcpy(p, utf8.c_str(), slen);
				p += slen;
			}
			break;
		case 1:
			{
				_int64 value = GetOptionVal(i+1);
				memcpy(p, &value, 8);
				p+=8;
			}
			break;
		default:
			return false;
		}
	}

	*p++ = (m_pOptionsSpeedLimitPage->m_DownloadSpeedLimits.size() >> 8) & 0xffu;
	*p++ = m_pOptionsSpeedLimitPage->m_DownloadSpeedLimits.size() % 256;
	for (auto const& limit : m_pOptionsSpeedLimitPage->m_DownloadSpeedLimits) {
		p = limit.FillBuffer(p);
	}

	*p++ = (m_pOptionsSpeedLimitPage->m_UploadSpeedLimits.size() >> 8) & 0xffu;
	*p++ = m_pOptionsSpeedLimitPage->m_UploadSpeedLimits.size() % 256;
	for (auto const& limit : m_pOptionsSpeedLimitPage->m_UploadSpeedLimits) {
		p = limit.FillBuffer(p);
	}

	*nBufferLength = len;

	return true;
}
Esempio n. 16
0
int CAdminSocket::ParseRecvBuffer()
{
	if (m_nRecvBufferPos<5)
		return 0;

	if ((m_pRecvBuffer[0]&0x03) != 0)
	{
		SendCommand(_T("Protocol error: Unknown command type, closing connection."), 1);
		Close();
		m_pAdminInterface->Remove(this);
		return -1;
	}
	else
	{
		DWORD len;
		memcpy(&len, m_pRecvBuffer+1, 4);
		if (len > 0xFFFFFF)
		{
			SendCommand(_T("Protocol error: Invalid data length, closing connection."), 1);
			Close();
			m_pAdminInterface->Remove(this);
			return -1;
		}
		if (m_nRecvBufferPos < len+5)
			return 0;
		else
		{
			int nID = (m_pRecvBuffer[0]&0x7C) >> 2;
			if (m_bStillNeedAuth)
			{
				if (nID)
				{
					SendCommand(_T("Protocol error: Not authenticated, closing connection."), 1);
					Close();
					m_pAdminInterface->Remove(this);
					return -1;
				}
				if (len != 16)
				{
					SendCommand(_T("Protocol error: Auth data len invalid, closing connection."), 1);
					Close();
					m_pAdminInterface->Remove(this);
					return -1;
				}
				MD5 md5;
				md5.update(m_Nonce1, 8);
				COptions options;
				CStdString pass = options.GetOption(OPTION_ADMINPASS);
				if (pass.GetLength() < 6)
				{
					SendCommand(_T("Protocol error: Server misconfigured, admin password not set correctly"), 1);
					Close();
					m_pAdminInterface->Remove(this);
					return -1;
				}
				auto utf8 = ConvToNetwork(pass);
				if (utf8.empty() && !pass.empty())
				{
					SendCommand(_T("Failed to convert password to UTF-8"), 1);
					Close();
					m_pAdminInterface->Remove(this);
					return -1;
				}
				md5.update((unsigned char *)utf8.c_str(), utf8.size());
				md5.update(m_Nonce2, 8);
				md5.finalize();
				unsigned char *digest = md5.raw_digest();
				if (memcmp(m_pRecvBuffer + 5, digest, 16))
				{
					delete [] digest;
					SendCommand(_T("Protocol error: Auth failed, closing connection."), 1);
					Close();
					m_pAdminInterface->Remove(this);
					return -1;
				}
				delete [] digest;

				FinishLogon();
			}
			else
				m_pAdminInterface->ProcessCommand(this, nID, m_pRecvBuffer+5, len);
			memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5);
			m_nRecvBufferPos-=len+5;
		}
	}
	return 1;
}