#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "Util.h"
#include "Filter.h"

char g_dll_path[128];

CSocketFilter::CSocketFilter()
{
	m_pFilterInfo =NULL;
	m_nFilterInfoCount =0;
	
	FILE *fp;

	if(GetProfileString("APIHook", "dll_path", "", g_dll_path, sizeof(g_dll_path)) ==0)
		return;
	char init_file[128];

	wsprintf(init_file, "%s\\filter.ini", g_dll_path);
	//WriteLog("FilterInit:init_file=%s", init_file);
	if((fp =fopen(init_file, "r")) ==NULL)
		return;
	char buf[300], *p, app[40], type[10], ip[16], buf1[256];
	int port;
	while(!feof(fp) && fgets(buf, sizeof(buf), fp))
	{
		if(strlen(buf) <5 || buf[0] =='#') continue;
		if(buf[strlen(buf)-1] =='\r' || buf[strlen(buf)-1] =='\n')
			buf[strlen(buf)-1] =0;
		if(buf[strlen(buf)-2] =='\r' || buf[strlen(buf)-2] =='\n')
			buf[strlen(buf)-2] =0;
		
		p =strtok(buf, ",");
		if(!p) continue;
		if(strlen(p) >= sizeof(type)) continue;
		strcpy(type, p);
		//WriteLog("type=%s", type);
		
		p =strtok(NULL, ",");
		if(!p) continue;
		if(strlen(p) >=sizeof(app)) continue;
		strcpy(app, p);
		//WriteLog("app=%s", app);


		p =strtok(NULL, ",");
		if(!p) continue;
		if(strcmpi(type, "dns"))
		{
			if(strlen(p) >=sizeof(ip)) continue;
			strcpy(ip, p);
			//WriteLog("ip=%s", ip);

			p =strtok(NULL, ",");
			if(!p) continue;
			if(*p !='*') port =atoi(p);
			else port =0;
			buf1[0] =0;
			if(!strcmpi(type, "recv") || !strcmpi(type, "send") || !strcmpi(type, "sendto") || !strcmpi(type, "recvfrom"))
			{
				p =strtok(NULL, ",");
				//if(!p) continue;
				if(p)
				{
					if(strlen(p) >=sizeof(buf1)) continue;
					strcpy(buf1, p);
				}
			}
		}
		else
		{
			if(strlen(p) >=sizeof(buf)) continue;
			strcpy(buf, p);
		}
		//WriteLog("buf1=%s", buf1);
		if(m_pFilterInfo)
			m_pFilterInfo =(FILTER_INFO *)realloc(m_pFilterInfo, (m_nFilterInfoCount+1)*sizeof(FILTER_INFO));
		else
			m_pFilterInfo =(FILTER_INFO *)malloc((m_nFilterInfoCount+1)*sizeof(FILTER_INFO));
		strcpy(m_pFilterInfo[m_nFilterInfoCount].app, app);
		if(!strcmpi(type, "connect"))
			m_pFilterInfo[m_nFilterInfoCount].type =FILTER_CONNECT;
		else if(!strcmpi(type, "bind"))
			m_pFilterInfo[m_nFilterInfoCount].type =FILTER_BIND;
		else if(!strcmpi(type, "accept"))
			m_pFilterInfo[m_nFilterInfoCount].type =FILTER_ACCEPT;
		else if(!strcmpi(type, "recv"))
			m_pFilterInfo[m_nFilterInfoCount].type =FILTER_RECV;
		else if(!strcmpi(type, "send"))
			m_pFilterInfo[m_nFilterInfoCount].type =FILTER_SEND;
		else if(!strcmpi(type, "sendto"))
			m_pFilterInfo[m_nFilterInfoCount].type =FILTER_SENDTO;
		else if(!strcmpi(type, "recvfrom"))
			m_pFilterInfo[m_nFilterInfoCount].type =FILTER_RECVFROM;
		else
			m_pFilterInfo[m_nFilterInfoCount].type =-1;

		strcpy(m_pFilterInfo[m_nFilterInfoCount].ip, ip);
		strcpy(m_pFilterInfo[m_nFilterInfoCount].buf, buf1);
		m_pFilterInfo[m_nFilterInfoCount].port =port;
		m_nFilterInfoCount++;
	}
}

CSocketFilter::~CSocketFilter()
{
	if(m_pFilterInfo)
		free(m_pFilterInfo);
}

int CSocketFilter::FilterBind(int port)
{
	char app[128];

	GetFileName(app);
	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		if(m_pFilterInfo[i].type !=FILTER_BIND)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(m_pFilterInfo[i].port ==port)
				return true;
		}
	}
	return false;
}

int CSocketFilter::FilterConnect(char *ip, int port)
{
	char app[128];

	GetFileName(app);
	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		if(m_pFilterInfo[i].type !=FILTER_CONNECT)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(m_pFilterInfo[i].ip[0] =='*' || !strcmpi(m_pFilterInfo[i].ip, ip))
			{
				if(m_pFilterInfo[i].port ==0 || m_pFilterInfo[i].port ==port)
					return true;
			}
		}
	}

	return false;
}

int CSocketFilter::FilterSend(int sd, char *buf, int len)
{
	char app[128];
	char ip[16];

	GetFileName(app);

	int port =GetLocalPortBySocket(sd);
	int port1 =GetRemotePortBySocket(sd);
	if(port1 <1024) port =port1;
	GetRemoteIPBySocket(sd, ip);

	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		if(m_pFilterInfo[i].type !=FILTER_SEND)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(m_pFilterInfo[i].ip[0] =='*' || !strcmpi(m_pFilterInfo[i].ip, ip))
			{
				if(m_pFilterInfo[i].port ==0 || m_pFilterInfo[i].port ==port)
				{
					if(m_pFilterInfo[i].buf[0] ==0) return true;
					mreplace(buf, len, m_pFilterInfo[i].buf, ' ');
				}
			}
		}
	}

	return false;
}

int CSocketFilter::FilterRecv(int sd, char *buf, int len)
{
	char app[128];
	char ip[16];

	GetFileName(app);

	int port =GetLocalPortBySocket(sd);
	int port1 =GetRemotePortBySocket(sd);
	if(port1 <1024) port =port1;
	GetRemoteIPBySocket(sd, ip);
	//WriteLog("FilterInfoCount=%d", m_nFilterInfoCount);
	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		WriteLog("FilterRecv:type=%d,app=%s,ip=%s,port=%d,buf=%s",
			m_pFilterInfo[i].type, m_pFilterInfo[i].app, m_pFilterInfo[i].ip,
			m_pFilterInfo[i].port,m_pFilterInfo[i].buf);

		if(m_pFilterInfo[i].type !=FILTER_RECV)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(m_pFilterInfo[i].ip[0] =='*' || !strcmpi(m_pFilterInfo[i].ip, ip))
			{
				if(m_pFilterInfo[i].port ==0 || m_pFilterInfo[i].port ==port)
				{
					//WriteLog("***************** mreplace...");
					if(m_pFilterInfo[i].buf[0] ==0) return true;
					mreplace(buf, len, m_pFilterInfo[i].buf, ' ');
				}
			}
		}
	}

	return false;
}

int CSocketFilter::FilterDNS(char *host_name)
{
	char app[128];

	GetFileName(app);

	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		if(m_pFilterInfo[i].type !=FILTER_RECV)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(!strcmpi(host_name, m_pFilterInfo[i].buf))
				return true;
		}
	}
	
	return false;
}

int CSocketFilter::FilterSendTo(char *ip, int port, char *buf, int len)
{
	char app[128];

	GetFileName(app);

	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		if(m_pFilterInfo[i].type !=FILTER_SENDTO)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(m_pFilterInfo[i].ip[0] =='*' || !strcmpi(m_pFilterInfo[i].ip, ip))
			{
				if(m_pFilterInfo[i].port ==0 || m_pFilterInfo[i].port ==port)
				{
					if(m_pFilterInfo[i].buf[0] ==0) return true;
					mreplace(buf, len, m_pFilterInfo[i].buf, ' ');
				}
			}
		}
	}

	return false;
}

int CSocketFilter::FilterRecvFrom(char *ip, int port, char *buf, int len)
{
	char app[128];

	GetFileName(app);

	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		if(m_pFilterInfo[i].type !=FILTER_RECVFROM)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(m_pFilterInfo[i].ip[0] =='*' || !strcmpi(m_pFilterInfo[i].ip, ip))
			{
				if(m_pFilterInfo[i].port ==0 || m_pFilterInfo[i].port ==port)
				{
					if(m_pFilterInfo[i].buf[0] ==0) return true;
					mreplace(buf, len, m_pFilterInfo[i].buf, ' ');
				}
			}
		}
	}

	return false;
}

int CSocketFilter::FilterAccept(int sd)
{
	char ip[16];
	int port =GetLocalPortBySocket(sd);
	GetRemoteIPBySocket(sd, ip);

	char app[128];

	GetFileName(app);
	
	for(int i=0; i<m_nFilterInfoCount; i++)
	{
		if(m_pFilterInfo[i].type !=FILTER_ACCEPT)
			continue;
		if(m_pFilterInfo[i].app[0] =='*' || !strcmpi(m_pFilterInfo[i].app, app))
		{
			if(m_pFilterInfo[i].ip[0] =='*' || !strcmpi(m_pFilterInfo[i].ip, ip))
			{
				if(m_pFilterInfo[i].port ==0 || m_pFilterInfo[i].port ==port)
					return true;
			}
		}
	}

	return false;
}
