// Adds a prefix to the titles of HTML pages.
//

#include "stdafx.h"
#include <crtdbg.h>
#include "ProtocolFilters.h"
#include "PFEventsDefault.h"

using namespace nfapi;
using namespace ProtocolFilters;

// Change this string after renaming and registering the driver under different name
#define NFDRIVER_NAME "netfilter2"

std::string g_titlePrefix;

class HttpFilter : public PFEventsDefault
{
public:
	HttpFilter()
	{
	}

	virtual void tcpConnected(nfapi::ENDPOINT_ID id, nfapi::PNF_TCP_CONN_INFO pConnInfo)
	{
//		if (pConnInfo->direction == NF_D_OUT)
		{
			pf_addFilter(id, FT_PROXY, FF_PROXY_INDICATE_HTTPS_PROXY_RESPONSE);
			pf_addFilter(id, FT_SSL, FF_SSL_SUPPORT_CLIENT_CERTIFICATES);
			pf_addFilter(id, FT_HTTP, FF_HTTP_FILTER_WEBSOCKET | FF_HTTP_BLOCK_SPDY | FF_HTTP_IGNORE_RESPONSE_ERRORS);
		}
	}

	void dataAvailable(nfapi::ENDPOINT_ID id, PFObject * object)
	{
		if ((object->getType() == OT_HTTP_RESPONSE) && 
			(object->getStreamCount() == 3))
		{
			PFHeader h;

			if (pf_readHeader(object->getStream(HS_HEADER), &h))
			{
				PFHeaderField * pField = h.findFirstField("Content-Type");
				if (pField)
				{
					if (pField->value().find("text/html") == -1)
					{
						pf_postObject(id, object);
						return;
					}
				}
			}

			PFStream * pStream = object->getStream(HS_CONTENT);
			char * buf;

			if (pStream && pStream->size() > 0)
			{
				buf = (char*)malloc((size_t)pStream->size() + 1);
				if (buf)
				{
					pStream->read(buf, (tStreamSize)pStream->size());
					buf[pStream->size()] = '\0';

					for (char * p = buf; *p; p++)
					{
						if (strnicmp(p, "<title", 6) == 0)
						{
							p = p + 6;
							if (p = strchr(p, '>'))
							{
								tStreamSize len = (tStreamSize)pStream->size();
								pStream->reset();
								pStream->write(buf, (tStreamSize)(p - buf + 1));
								pStream->write(g_titlePrefix.c_str(), (tStreamSize)g_titlePrefix.length());
								pStream->write(p + 1, len - (p + 1 - buf));
							}
							break;
						}
					}
					free(buf);
				}
			}
		}

		pf_postObject(id, object);
	}

	PF_DATA_PART_CHECK_RESULT 
	dataPartAvailable(nfapi::ENDPOINT_ID id, PFObject * object)
	{
		if (object->getType() == OT_HTTP_RESPONSE)
		{
			PFHeader h;

			if (pf_readHeader(object->getStream(HS_HEADER), &h))
			{
				PFHeaderField * pField = h.findFirstField("Content-Type");
				if (pField)
				{
					if (pField->value().find("text/html") != -1)
					{
						return DPCR_FILTER;
					}
				}
			}
		}

		return DPCR_BYPASS;
	}

};

static unsigned char getMaskLength(unsigned char * mask, int len)
{
	unsigned char b;
	unsigned char maskLen = 0;

	for (int i=len-1; i>=0; i--)
	{
		b = mask[i];

		if (b == 255)
		{
			maskLen += 8;
			continue;
		}

		for (int j=7; j>=0; j--)
		{
			if (!(b & (1 << j)))
			{
				return maskLen;
			} 

			maskLen++;
		}
	}

	return maskLen;
}

int main(int argc, char* argv[])
{
	NF_RULE rule;

	if (argc < 2)
	{
		printf("Usage: PFHttpContentFilter <string>\n" \
			"<string> : add this to titles of HTML pages\n");
		return -1;
	}

	g_titlePrefix = argv[1];
	g_titlePrefix += " ";
	
#ifdef _DEBUG
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif


	nf_adjustProcessPriviledges();

	printf("Press any key to stop...\n\n");

	HttpFilter f;

	if (!pf_init(&f, L"c:\\netfilter2"))
	{
		printf("Failed to initialize protocol filter");
		return -1;
	}

	char send_buf[2000];
	size_t send_buf_len;

	FILE * ff = fopen("C:\\projects\\projectsJ\\nfsdk\\nfsdk\\sockfilter\\temp\\data\\send.bin ", "rb");
	if (ff)
	{
		send_buf_len = fread(send_buf, 1, sizeof(send_buf), ff);
		
		fclose(ff);
	}

	pf_setRootSSLCertSubject("Sample CA");

	NF_TCP_CONN_INFO ci;
	memset(&ci, 0, sizeof(ci));
	ci.direction = NF_D_OUT;
	ci.ip_family = AF_INET;
	ci.filteringFlag = NF_FILTER;

	char send0[] = 
		"POST /db/recover?fileName=safe_exam_20251226.db%26echo%2011%3E11.log HTTP/1.1\r\n" \
"Host: 192.168.1.226:8189\r\n" \
"Cookie: safe-exam-Token=eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjhiYzc4M2EwLTdmYjEtNDVlNy1hZjVmLTE5YjYzYjM1ZWZkZCJ9.zkZ3FNvzbwPPUolgrCtBd7cA6uhIMTlVed4Cozn_Fh3G8W3uYmOKOeufqcZ06XAs3Dcbdhv_AlG1UES3rRBuKw\r\n" \
"Accept: */*\r\n" \
"Accept-Language: zh-CN,zh;q=0.9\r\n" \
"Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjhiYzc4M2EwLTdmYjEtNDVlNy1hZjVmLTE5YjYzYjM1ZWZkZCJ9.zkZ3FNvzbwPPUolgrCtBd7cA6uhIMTlVed4Cozn_Fh3G8W3uYmOKOeufqcZ06XAs3Dcbdhv_AlG1UES3rRBuKw\r\n" \
"Cache-Control: no-cache\r\n" \
"Connection: keep-alive\r\n" \
"Content-Length: 0\r\n" \
"Content-Type: multipart/form-data; boundary=----WebKitFormBoundary3pEWE11FfgS5Hv8S\r\n" \
"Pragma: no-cache\r\n" \
"Referer: http://192.168.0.107:8189/safe/exam/examinee\r\n" \
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\r\n" \
"\r\n" \
"------WebKitFormBoundary3pEWE11FfgS5Hv8S\r\n" \
"Content-Disposition: form-data;" \
"name=\"fileName\"\r\n" \
"\r\n" \
"safe_exam_20250322150246111.db\r\n" \
"------WebKitFormBoundary3pEWE11FfgS5Hv8S--\r\n" \
"\r\n"
;

/*		 
	char send1[] = "CONNECT www.bbc.co.uk:443 HTTP/1.1\r\n" \
		"Host: www.bbc.co.uk:443" \
		"Auth: ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		;
*/
	char send2[] = "ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\r\n" \
		"\r\n\r\n";
//	char send2[] = "\"ARhMeWtvdi5BU0BnYXpwcm9tLW5lZnQucnUBLFUreWVGdzB2N1ZwSjhXSU9WNVdvU2s5bHlpZ0E3TC9OcDJreTE2OE1ZQWc9F11MUeLq1QgBARAdMRJoOcDMQrhna2\/bIcSLAQgyLjAuNS4xNgEFcnUtUlUBBXJ1LVJVARJBc2lhL1lla2F0ZXJpbmJ1cmc=\" ";

	char send3[] = "PUT http://login.scout365.ru:8081/login/2 HTTP/1.1\r\n" \
"Content-Type: application/json; charset=utf-8\r\n" \
"Host: login.scout365.ru:8081\r\n" \
"Content-Length: 0\r\n\r\n";

	char send_[] = "GET /nodes/create_from_stream.json?filename=7799c9d9-9ac2-4535-89bc-0fd0fa1d9a0e.txt&node[checksum]=c45bfe97bf6618a62b6ef03f804393bc&node[file_creation_date_unix]=1557897691&node[file_modification_date_unix]=1557840479&parent_uuid=0&return_405=true HTTP/1.1\r\n\
Host: krb-acronis.krb.lan\r\n\
Accept: */*\r\n\
Accept-Encoding: gzip,deflate\r\n\
Cookie: _activecho_session=e2526cd8970b0f58ea8449ecff89adc3\r\n\
Cache-control: max-age=0\r\n\
Connection: Keep-Alive\r\n\
Pragma: no-cache\r\n\
User-Agent: Files Advanced Client 8.5.0x348 (Windows 10)\r\n\
aecontent-length: 2280923\r\n\
authorization: Basic dGVzdDJAdGVzdC5sYW46UXdlcnR5MSE=\r\n\r\n";
	
	char receive0[] = "HTTP/1.1 204 OK\r\n" \
			"upgrade:websocket */*\r\n"\
			"\r\n" \
			"\r\n" \
			"aaa";


	char receive1_[] = "HTTP/1.1 200 Connection established\r\n\r\n";

	char receive1[] = "HTTP/1.1 405 Method Not Allowed\r\n\
Server: Apache-Coyote/1.1\r\n\
X-Frame-Options: SAMEORIGIN\r\n\
X-XSS-Protection: 1; mode=block\r\n\
X-Content-Type-Options: nosniff\r\n\
Strict-Transport-Security: max-age=31536000; includeSubDomains;\r\n\
Cache-Control: no-cache\r\n\
Set-Cookie: _activecho_session=e2526cd8970b0f58ea8449ecff89adc3; path=/; expires=Thu, 04 Oct 2068 11:18:39 -0000; secure; HttpOnly\r\n\
X-Request-Id: 54f969f2-1dec-44c9-b182-20d370bc5b57\r\n\
X-Runtime: 0.236452\r\n\
Content-Type: application/json;charset=utf-8\r\n\
Transfer-Encoding: chunked\r\n\
Date: Thu, 16 May 2019 05:39:19 GMT\r\n\
\r\n\
5c\r\n\
Узла с такой контрольной суммой уже не существует.\r\n";


	char receive2[] = "0\r\n";
	char receive3[] = "\r\n";

	int n = sizeof(sockaddr_in);

	pf_getNFEventHandler()->tcpConnected(1, &ci);

	pf_getNFEventHandler()->tcpSend(1, send_buf, send_buf_len);

//	pf_getNFEventHandler()->tcpSend(1, send1, sizeof(send1)-1);
//	pf_getNFEventHandler()->tcpSend(1, send2, sizeof(send2)-1);
	pf_getNFEventHandler()->tcpReceive(1, receive0, sizeof(receive0)-1);
//	pf_getNFEventHandler()->tcpReceive(1, receive2, sizeof(receive2)-1);
//	pf_getNFEventHandler()->tcpReceive(1, receive3, sizeof(receive3)-1);
//	pf_getNFEventHandler()->tcpSend(1, send2, sizeof(send2)-1);
//	pf_getNFEventHandler()->tcpSend(1, send3, sizeof(send3)-1);
//	pf_getNFEventHandler()->tcpReceive(1, NULL, 0);

/*
	// Initialize the library and start filtering thread
	if (nf_init(NFDRIVER_NAME, pf_getNFEventHandler()) != NF_STATUS_SUCCESS)
	{
		printf("Failed to connect to driver");
		return -1;
	}

	// Filter all TCP connections
	memset(&rule, 0, sizeof(rule));
	//rule.direction = NF_D_OUT;
	rule.protocol = IPPROTO_TCP;
	rule.filteringFlag = NF_FILTER;
	nf_addRule(&rule, TRUE);

	// Wait for any key
	getchar();

	// Free the libraries
	nf_free();
*/
	pf_free();

	return 0;
}

