#!/usr/bin/python3
###############################################################################
#                                                                             #
# Fireinfo                                                                    #
# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org)                       #
#                                                                             #
# 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 3 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, see <http://www.gnu.org/licenses/>.       #
#                                                                             #
###############################################################################

import json
import logging
import logging.handlers
import os
import sys
import urllib.request, urllib.parse, urllib.error

import fireinfo

ENABLED_FILE = "/var/ipfire/main/send_profile"
PROXY_SETTINGS = "/var/ipfire/proxy/advanced/settings"

log_level = logging.INFO
if "-d" in sys.argv:
	log_level = logging.DEBUG

# Setup logging
log = logging.getLogger()
log.setLevel(log_level)
log.addHandler(logging.handlers.SysLogHandler("/dev/log"))
log.addHandler(logging.StreamHandler(sys.stderr))
for handler in log.handlers:
	handler.setLevel(log_level)

PROFILE_URL = "https://fireinfo.ipfire.org/send/%(public_id)s"

def get_upstream_proxy():
	if not os.path.exists(PROXY_SETTINGS):
		return {"host" : ""}

	proxy_settings = {}
	with open(PROXY_SETTINGS) as f:
		for line in f.readlines():
			k, v = line.split("=", 1)
			proxy_settings[k] = v.strip()

	return {
		"host" : proxy_settings.get("UPSTREAM_PROXY", ""),
		"user" : proxy_settings.get("UPSTREAM_USER", ""),
		"pass" : proxy_settings.get("UPSTREAM_PASSWORD", ""),
	}

def send_profile(profile):
	logging.debug("Sending profile:")
	for line in json.dumps(profile, sort_keys=True, indent=4).splitlines():
		logging.debug(line)

	# Compile payload
	data = urllib.parse.urlencode({"profile" : json.dumps(profile)})

	request = urllib.request.Request(PROFILE_URL % profile, data=data.encode())
	request.add_header("User-Agent", "fireinfo/%s" % fireinfo.__version__)

	# Set upstream proxy if we have one.
	proxy = get_upstream_proxy()

	if proxy["host"]:
		# handling upstream proxies with authentication is more tricky...
		if proxy["user"] and proxy["pass"]:
			prx_auth_string = "http://%s:%s@%s/" % (proxy["user"], proxy["pass"], proxy["host"])

			proxy_handler = urllib.request.ProxyHandler({'http': prx_auth_string, 'https': prx_auth_string})
			auth = urllib.request.HTTPBasicAuthHandler()
			opener = urllib.request.build_opener(proxy_handler, auth, urllib.request.HTTPHandler)
			urllib.request.install_opener(opener)
		else:
			request.set_proxy(proxy["host"], "http")
			request.set_proxy(proxy["host"], "https")

	try:
		urllib.request.urlopen(request, timeout=60)
	except (urllib.error.HTTPError, urllib.error.URLError) as e:
		reason = "Unknown reason"

		if isinstance(e, urllib.error.HTTPError):
			reason = "%s" % e
		elif isinstance(e, urllib.error.URLError):
			reason = e.reason

		logging.error("Profile was not sent propertly: %s" % reason)
		return

	logging.debug("Profile was sent successfully.")

def main():
	# Collect system information
	system = fireinfo.System()
	profile = system.profile()

	# If --dump is passed -> only dump the output.
	if "--dump" in sys.argv:
		# Remove the private id when dumping the profile because
		# it contains no information and may confuse people.
		del profile["private_id"]

		print(json.dumps(profile, sort_keys=True, indent=4))
		return 0

	if "--secret-id" in sys.argv:
		print(system.secret_id)
		return 0

	if "--hardware-string" in sys.argv:
		print(system._unique_id)
		return 0

	if "--public-id" in sys.argv:
		print(system.public_id)
		return 0

	if not os.path.exists(ENABLED_FILE):
		del profile["profile"]

	try:
		send_profile(profile)
	except urllib.error.URLError:
		return 1

	return 0

sys.exit(main())
