import requests
import socket
from data_helpers import *

HTTP_Prefix = 'http://' #@Todo: use href also.
DOUBLE_QUOTE = '"'
FORWARD_SLASH = "/"


def host_matches(ip_list_known, ip_list_check):
	for ip_check in ip_list_check:
		if ip_check in ip_list_known:
			##print("HOST_MATCHES!", ip_list_known, ip_list_check)
			return True

	return False


def nslookup(host):
	ip_list = []
	ais = socket.getaddrinfo(host,0,0,0,0)
	for result in ais:
	  ip_list.append(result[-1][0])
	ip_list = list(set(ip_list))
	##print("IPLIST FOR ", host, "\nLIST: ", ip_list)
	return ip_list


def split_href(split_response, host, previous_level_links):
	split_response = split_response.split('href="') # (DOUBLE_QUOTE + HTTP_Prefix)
	for i in range(0, len(split_response)):
		if HTTP_Prefix in split_response[i]:
			split_response[i] = split_response[i].split(HTTP_Prefix)[1]


	links = []

	for segment in split_response[1:]:
		split_segment = segment.split(DOUBLE_QUOTE)[0]
		try:
			if split_segment[0] == "#":
				split_segment = host + FORWARD_SLASH + split_segment
			elif split_segment[0] == "/":
				split_segment = host + split_segment

			link = HTTP_Prefix + split_segment
			###print(link)
			if (previous_level_links is None or link not in previous_level_links) and (link not in links):
				links.append(link)
				###print("Adding " + link)
		except:
			pass
			#print("Failed on: ", segment, ", split to: ", split_segment)

	return links

def split_http(split_response, host, previous_level_links):
	split_response = split_response.split(DOUBLE_QUOTE + HTTP_Prefix)

	links = []

	for segment in split_response[1:]:
		split_segment = segment.split(DOUBLE_QUOTE)[0]

		link = HTTP_Prefix + split_segment
		###print(link)
		if (previous_level_links is None or link not in previous_level_links) and (link not in links):
			links.append(link)
			###print("Adding " + link)

	return links


def clean_links(links):
	new_links = []
	for link in links:
		if not ("mailto:" in link or "https:" in link or "favicon.ico" in link or ".zip" in link or ".xml" in link or ".png" in link):
			new_links.append(link)

	return new_links

# @Todo: crawler does not correctly traverse to other ports.
def http_crawl(url, host, crawl_externally, previous_level_links = None, verbose = False):
	if verbose:
		print("Crawling to: " + url + ", Host: " + host)
		
	#Get address info of host
	host_ip_list = nslookup(host)

	try:
		response = requests.get(url=url)  # using HTTP Requests for humans: http://docs.python-requests.org/en/latest/
		###print(response.text)
	except:
		##print("Request failed. Service is not HTTP.")
		return None, None

	if response.status_code == 404:
		return None, None


	##print("Recvd response.")

	split_response = response.text.replace(' ', '')

	contains_form = False
	if "<form" in split_response:
		##print("Page contains forms!")
		contains_form = True	
	
	links_href = split_href(split_response, host, previous_level_links)
	links_http = split_http(split_response, host, previous_level_links)
	links = append_list_if_not_exist(links_href, links_http)
	links = clean_links(links)


	form_dict = {}
	form_dict[url] = contains_form

	this_level_links = links.copy()
	if previous_level_links:
		this_level_links = this_level_links + previous_level_links.copy()

	this_level_links.append(url)
	##print("Number of links: " + str(len(links)))


	valid_links = {}
	for link in links:
		link_host = link.split(HTTP_Prefix)[1].split(FORWARD_SLASH)[0]
		##print(link_host)
		try:
			link_ip_list = nslookup(link_host)
			if host_matches(host_ip_list, link_ip_list) or crawl_externally:
				valid_links[link] = link_host
				##print("MATCH: " + link)
		except:
			##print("Skipping: " + link)
			pass


	lower_level_links = []
	#Find all links
	for link in valid_links.keys():
		###print("Crawling to: " + link)
		collected_links, collected_form_dict = http_crawl(link, valid_links[link], crawl_externally, this_level_links, verbose =verbose)
		append_list_if_not_exist(lower_level_links, collected_links)
		append_list_if_not_exist(this_level_links, collected_links)#make sure we don't visit the same page twice.
		form_dict = merge_form_dicts(form_dict, collected_form_dict)
	

	
	append_list_if_not_exist(lower_level_links, list(valid_links.keys()))
	return lower_level_links, form_dict


def form_parse(url, ip, port):
	XSS = '<script>alert("THIS PAGE IS VULNERABLE TO XSS");</script>'
	response = requests.get(url=url)
	##print(response.text)
	split_response = response.text.replace(' ', '').replace('\n', '').lower()
	form_text = split_response.split("<form")[1:]


	form_list = []

	for form in form_text:
		form_list.append(form.split("</form")[0])

	action = None
	payload = {}

	try:
		for form in form_list:
			#pass
			action = form.split('action="')[1].split('"')[0]
			inputs = form.split('<input')[1:]
			textareas = form.split('<textarea')[1:]

			if action[0] != '/':
				action = '/' + action

			#print("ACTION: ", action)

			names = []

			for input in inputs:
				#print("INPUT", input)
				name = input.split('name="')[1].split('"')[0]
				#print("NAME", name)
				names.append(name)

			for textarea in textareas:
				#print("TEXTAREA", textarea)
				name = textarea.split('name="')[1].split('"')[0]
				#print("NAME", name)
				names.append(name)


		for name in names:
			if name != "submit":
				payload[name] = XSS

		#print("PAYLOAD", payload)
	except:
		#print("COULD NOT PARSE FORM!!!")
		pass



	post_url = "http://" + ip + ":" + str(port) + action
	#print("POSTING TO: ", post_url)

	response = requests.post(post_url, data=payload) #@TODO build url from ACTION
	if XSS in response.text:
		#print("VULNERABLE!!!!")
		return True

	return False