Server : Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6
System : Windows NT USER-PC 6.1 build 7601 (Windows 7 Professional Edition Service Pack 1) AMD64
User : User ( 0)
PHP Version : 7.4.6
Disable Function : NONE
Directory :  C:/xampp/FileZillaFTP/source/
Upload File :
Current Directory [ Writeable ] Root Directory [ Writeable ]


Current File : C:/xampp/FileZillaFTP/source/ExternalIpCheck.cpp
// FileZilla Server - a Windows ftp server

// Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include "stdafx.h"
#include "ExternalIpCheck.h"
#include "ServerThread.h"
#include "Options.h"

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

#define TIMERINTERVAL 30

CExternalIpCheck::CExternalIpCheck(CServerThread *pOwner)
{
	ASSERT(pOwner);
	m_pOwner = pOwner;

	m_bActive = FALSE;
	m_nRetryCount = 0;
	m_nTimerID = SetTimer(0, 0, TIMERINTERVAL * 1000, 0);
	m_bTriggerUpdateCalled = FALSE;
	m_nFailedConnections = 0;
	m_nElapsedSeconds = 0;
	
	if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
		return;
	
	if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 2)
		Start();
	else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1)
	{
		CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP);
		SOCKADDR_IN sockAddr;
		memset(&sockAddr, 0, sizeof(sockAddr));
		
		sockAddr.sin_family = AF_INET;
#ifdef _UNICODE
		sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname));
#else
		sockAddr.sin_addr.s_addr = inet_addr(hostname);
#endif
		
		if (sockAddr.sin_addr.s_addr == INADDR_NONE)
		{
			LPHOSTENT lphost;
#ifdef _UNICODE
			lphost = gethostbyname(ConvToLocal(hostname));
#else
			lphost = gethostbyname(hostname);
#endif
			if (lphost != NULL)

				sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
			else
			{
				Close();
				m_nRetryCount++;
				m_bActive = FALSE;
				return;
			}
		}
		
		const char *ip = inet_ntoa(sockAddr.sin_addr);
		
		if (!ip)
			return;
		
#ifdef _UNICODE
		m_IP = ConvFromLocal(ip);
#else
		m_IP = ip;
#endif
	}
}

CExternalIpCheck::~CExternalIpCheck()
{
	Close();
}

void CExternalIpCheck::OnReceive(int nErrorCode)
{
	if (!m_bActive)
		return;

	if (nErrorCode)
	{
		m_bActive = FALSE;
		Close();
		m_nRetryCount++;
		return;
	}
	char buffer[1000];
	int len = Receive(buffer, 999);

	if (len == SOCKET_ERROR)
	{
		if (GetLastError() == WSAEWOULDBLOCK)
			return;
	
		Close();
		m_nRetryCount++;
		m_bActive = FALSE;
		return;
	}

	buffer[len] = 0;
	char *p = strstr(buffer, "\r\n\r\n");
	if (!p)
		p = strstr(buffer, "\n\n");

	if (!p)
	{
		Close();
		m_nRetryCount++;
		m_bActive = FALSE;
		return;
	}
	
	
	while (*p && (*p == '\n' || *p == '\r'))
		p++;

	if (!*p)
	{
		Close();
		m_nRetryCount++;
		m_bActive = FALSE;
		return;
	}

	char * ip = p;
	while (*p && *p != '\n' && *p != '\r')
		p++;
	*p = 0;
	
	SOCKADDR_IN sockAddr;
	memset(&sockAddr,0,sizeof(sockAddr));
	
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = inet_addr(ip);
	
	if (sockAddr.sin_addr.s_addr == INADDR_NONE)
	{
		LPHOSTENT lphost;
		lphost = gethostbyname(ip);
		if (lphost != NULL)
			sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
		else
		{
			Close();
			m_nRetryCount++;
			m_bActive = FALSE;
			return;
		}
	}
	
	ip = inet_ntoa(sockAddr.sin_addr);

	if (!ip)
	{		
		Close();
		m_nRetryCount++;
		m_bActive = FALSE;
		return;
	}
	
#ifdef _UNICODE
	m_IP = ConvFromLocal(ip);
#else
	m_IP = ip;
#endif

	m_nFailedConnections = 0;

	Close();
	m_nRetryCount = 0;
	m_bActive = FALSE;
}

void CExternalIpCheck::OnConnect(int nErrorCode)
{
	if (!m_bActive)
		return;

	if (nErrorCode)
	{
		m_bActive = FALSE;
		Close();
		m_nRetryCount++;
		return;
	}
	
	CStdStringA address = "GET " + m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIPSERVER) + " HTTP/1.0\r\nUser-Agent: FileZilla Server\r\n\r\n";
	const char *buffer = address;
	int len = strlen(buffer);
	if (Send(buffer, len) != len)
	{
		m_bActive = FALSE;
		Close();
		m_nRetryCount++;
	}

	OnReceive(0);
}

void CExternalIpCheck::OnTimer()
{
	if (m_nElapsedSeconds <= 1000000)
		m_nElapsedSeconds += TIMERINTERVAL;

	if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
	{
		m_nRetryCount = 0;
		Close();
		m_bActive = FALSE;
		return;
	}
	else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1)
	{
		m_nRetryCount = 0;
		Close();
		m_bActive = FALSE;

		CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP);
		SOCKADDR_IN sockAddr;
		memset(&sockAddr,0,sizeof(sockAddr));
		
		sockAddr.sin_family = AF_INET;
#ifdef _UNICODE
		sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname));
#else
		sockAddr.sin_addr.s_addr = inet_addr(hostname);
#endif
		
		if (sockAddr.sin_addr.s_addr == INADDR_NONE)
		{
			LPHOSTENT lphost;
#ifdef _UNICODE
			lphost = gethostbyname(ConvToLocal(hostname));
#else
			lphost = gethostbyname(hostname);
#endif
			if (lphost != NULL)
				sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
			else
			{
				Close();
				m_nRetryCount++;
				m_bActive = FALSE;
				return;
			}
		}
		
		const char *ip = inet_ntoa(sockAddr.sin_addr);
		
		if (!ip)
			return;
	
#ifdef _UNICODE
		m_IP = ConvFromLocal(ip);
#else
		m_IP = ip;
#endif
		m_nFailedConnections = 0;
		return;
	}

	if (!m_bActive && m_nRetryCount)
	{
		if (m_nElapsedSeconds > 60 && m_nRetryCount < 5)
		{
			Start();
			return;
		}
		else if (m_nElapsedSeconds > 300 && m_nRetryCount < 10)
		{
			Start();
			return;
		}
		else if (m_nElapsedSeconds > 900 && m_nRetryCount < 20)
		{
			Start();
			return;
		}
		else if (m_nElapsedSeconds > 3600)
		{
			Start();
			return;
		}
	}
	else if (m_bActive)
	{
		if (m_nElapsedSeconds > 30)
		{
			m_bActive = FALSE;
			Close();
			m_nRetryCount++;
			m_nElapsedSeconds = 0;
		}
	}
	else
	{
		if (m_nElapsedSeconds > 300 && m_bTriggerUpdateCalled)
			Start();
		else if (m_nElapsedSeconds > 3600)
			Start();
	}
}

void CExternalIpCheck::OnClose(int nErrorCode)
{
	if (m_bActive)
	{
		m_bActive = FALSE;
		Close();
		m_nRetryCount++;
	}
}

void CExternalIpCheck::Start()
{
	if (m_bActive)
		return;

	CStdString address = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIPSERVER);
	if (address.Left(7) == _T("http://"))
		address = address.Mid(7);
	int pos = address.Find('/');
	if (pos != -1)
		address = address.Left(pos);
	if (address == _T(""))
		return;

	m_bTriggerUpdateCalled = FALSE;

	m_nElapsedSeconds = 0;
	Create();

	BOOL res = Connect(address, 80);
	if (res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK)
		m_nRetryCount++;
	else
		m_bActive = TRUE;
}

void CExternalIpCheck::TriggerUpdate()
{
	if (m_bActive)
		return;

	m_bTriggerUpdateCalled = TRUE;
	if (m_nFailedConnections < 100000)
		m_nFailedConnections++;
}

CStdString CExternalIpCheck::GetIP(const CStdString& localIP)
{
	if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
		return _T("");

	CStdString ip;
	switch (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
	{
	case 0:
		return _T("");
	case 2:
		if (!m_bActive && !m_nRetryCount && localIP != _T(""))
		{
			if (localIP == m_IP)
				m_nElapsedSeconds = 0;
		}
	case 1:
		ip = m_IP;
		
		break;
	}
	
	return ip;
}