#!/usr/bin/env python

import gtk
import os
import sys
import re

# Internationalization
import locale
import gettext
import gtk.glade
gettext.bindtextdomain("gtkhostsetup", "/usr/share/locale")
gettext.textdomain("gtkhostsetup")
gettext.install("gtkhostsetup", "/usr/share/locale", unicode=1)
gtk.glade.bindtextdomain("gtkhostsetup", "/usr/share/locale")
gtk.glade.textdomain("gtkhostsetup")

hostname_file='/etc/HOSTNAME'
hosts_file='/etc/hosts'

def get_hostname():
	try:
		f = file(hostname_file)
		line = f.readline().replace('\n', '')
		f.close()
	except IOError:
		return ['','']
	if len(line) == 0:
		return ['', '']
	else:
		hostname=line.partition('.')[0]
		domain=line.partition('.')[2]
		return [hostname, domain]

def get_other_hosts():
	try:
		f = file(hosts_file)
		contents = f.readlines()
		f.close()
	except IOError:
		return [[]]
	hostlines=[]
	for line in contents:
		temp = line.replace('\t', ' ').replace('\n', '').partition('#')[0].split()
		line = ' '.join(temp)
		if not line == '':
			ip = line.partition(' ')[0]
			hostname = line.partition(' ')[2].partition('.')[0]
			domain = line.partition(' ')[2].partition('.')[2].partition(' ')[0]
			if not ip == '127.0.0.1':
				hostlines.append([ip, hostname, domain])
	return sorted(hostlines)


def check_hostname(ip, hostname, domain):
	error = False
	msg = ''
	if ip == '':
		error = True
		msg = _('The IP address cannot be empty.')
	elif hostname == '':
		error = True
		msg = _('The hostname cannot be empty.')
	elif hostname.startswith('-'):
		error = True
		msg = _('The hostname cannot start with a hyphen.')
	elif hostname.endswith('-'):
		error = True
		msg = _('The hostname cannot end with a hyphen.')
	elif domain.startswith('-'):
		error = True
		msg = _('The domain cannot start with a hyphen.')
	elif domain.endswith('-'):
		error = True
		msg = _('The domain cannot end with a hyphen.')
	if error == False:
		for i in ip:
			if not re.match("^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$", ip):
				error = True
				msg = _('Not a valid IP address.')
	if error == False:
		for i in hostname:
			if not i in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-':
				error = True
				msg = _('The hostname can consist solely of latin letters, numbers and hyphens.')
	if error == False:
		for i in domain:
			if not i in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.':
				error = True
				msg = _('The domain can consist solely of latin letters, numbers, hyphens and dots.')
	return error, msg

def write_hosts(hostname, domain, host_list):
	f = file(hostname_file, 'w')
	if domain == '':
		f.write(hostname+'\n')
	else:
		f.write(hostname+'.'+domain+'\n')
	f.close()
	f = file(hosts_file, 'w')
	f.write('#\n')
	f.write('# hosts\tThis file describes a number of hostname-to-address\n')
	f.write('#\t\tmappings for the TCP/IP subsystem. It is mostly\n')
	f.write('#\t\tused at boot time, when no name servers are running.\n')
	f.write('#\t\tOn small systems, this file can be used instead of a\n')
	f.write('#\t\t"named" name server.  Just add the names, addresses\n')
	f.write('#\t\tand any aliases to this file...\n')
	f.write('#\n')
	f.write('# By the way, Arnt Gulbrandsen <agulbra@nvg.unit.no> says that 127.0.0.1\n')
	f.write('# should NEVER be named with the name of the machine. It causes problems\n')
	f.write('# for some (stupid) programs, irc and reputedly talk. :^)\n')
	f.write('#\n')
	f.write('# For loopbacking.\n')
	f.write('127.0.0.1\tlocalhost\n')
	if domain == '':
		f.write('127.0.0.1\t'+hostname+'\n\n')
	else:
		f.write('127.0.0.1\t'+hostname+'.'+domain+' '+hostname+'\n\n')
	for i in host_list:
		ip, hostname, domain = i
		if domain == '':
			f.write(ip+'\t'+hostname+'\n')
		else:
			f.write(ip+'\t'+hostname+'.'+domain+' '+hostname+'\n')
	f.write('\n# End of hosts.\n')
	f.close()

class GTKHostSetup:
	def on_button_about_clicked(self, widget, data=None):
		self.aboutdialog.show()

	def on_aboutdialog_response(self, widget, data=None):
		self.aboutdialog.hide()

	def on_aboutdialog_delete_event(self, widget, event):
		self.aboutdialog.hide()
		return True

	def create_host_list(self, widget):
		for i in get_other_hosts():
			self.liststore_hosts.append(i)

	def on_button_ok_clicked(self, widget, data=None):
		this_hostname = self.entry_hostname.get_text()
		this_domain = self.entry_domain.get_text()
		error, message = check_hostname('127.0.0.1', this_hostname, this_domain)
		if error:
			self.label_main_error.set_text(message)
			self.error_main_window.show()
		else:
			host_list = []
			iter = self.liststore_hosts.get_iter_root()
			while (iter):
				ip = self.liststore_hosts.get_value(iter, 0)
				hostname = self.liststore_hosts.get_value(iter, 1)
				domain = self.liststore_hosts.get_value(iter, 2)
				host_list.append([ip, hostname, domain])
				iter = self.liststore_hosts.iter_next(iter)
			write_hosts(self.entry_hostname.get_text(), self.entry_domain.get_text(), sorted(host_list))
			gtk.main_quit()

	def on_button_cancel_clicked(self, widget, data=None):
		gtk.main_quit()

	def gtk_main_quit(self, widget, data=None):
		gtk.main_quit()
	
	def on_button_add_clicked(self, widget, data=None):
		self.add_host_window.show()

	def on_add_host_window_delete_event(self, widget, data=None):
		self.add_host_window.hide()
		return True
	
	def on_button_edit_clicked(self, widget, data=None):
		try:
			host = self.treeview_hosts.get_selection()
			self.liststore_hosts, iter = host.get_selected()
			self.entry_edit_ip.set_text(self.liststore_hosts.get_value(iter, 0))
			self.entry_edit_hostname.set_text(self.liststore_hosts.get_value(iter, 1))
			self.entry_edit_domain.set_text(self.liststore_hosts.get_value(iter, 2))
			self.edit_host_window.show()
		except TypeError:
			pass

	def on_button_edit_ok_clicked(self, widget, data=None):
		ip = self.entry_edit_ip.get_text()
		hostname = self.entry_edit_hostname.get_text()
		domain = self.entry_edit_domain.get_text()
		error, message = check_hostname(ip, hostname, domain)
		if error:
			self.label_edit_error.set_text(message)
			self.edit_error_window.show()
		else:
			try:
				self.edit_host_window.hide()
				host = self.treeview_hosts.get_selection()
				self.liststore_hosts, iter = host.get_selected()
				self.liststore_hosts.remove(iter)	
				self.liststore_hosts.append([ip, hostname, domain])
				self.entry_edit_ip.set_text('')
				self.entry_edit_hostname.set_text('')
				self.entry_edit_domain.set_text('')
				self.liststore_hosts.set_sort_column_id(0, gtk.SORT_ASCENDING)
			except TypeError:
				pass

	def on_button_edit_cancel_clicked(self, widget, data=None):
		self.edit_host_window.hide()

	def on_edit_host_window_delete_event(self, widget, data=None):
		self.edit_host_window.hide()
		return True

	def on_button_delete_clicked(self, widget, data=None):
		try:
			host = self.treeview_hosts.get_selection()
			self.liststore_hosts, iter = host.get_selected()
			self.liststore_hosts.remove(iter)	
		except TypeError:
			pass

	def on_button_add_ok_clicked(self, widget, data=None):
		ip = self.entry_new_ip.get_text()
		hostname = self.entry_new_hostname.get_text()
		domain = self.entry_new_domain.get_text()
		error, message = check_hostname(ip, hostname, domain)
		if error:
			self.label_add_error.set_text(message)
			self.add_error_window.show()
		else:
			self.add_host_window.hide()
			self.liststore_hosts.append([ip, hostname, domain])
			self.entry_new_ip.set_text('')
			self.entry_new_hostname.set_text('')
			self.entry_new_domain.set_text('')
			self.liststore_hosts.set_sort_column_id(0, gtk.SORT_ASCENDING)

	def on_button_add_cancel_clicked(self, widget, data=None):
		self.add_host_window.hide()

	def on_button_add_error_ok_clicked(self, widget, data=None):
		self.add_error_window.hide()

	def on_add_error_window_delete_event(self, widget, data=None):
		self.add_error_window.hide()
		return True

	def on_button_edit_error_ok_clicked(self, widget, data=None):
		self.edit_error_window.hide()

	def on_edit_error_window_delete_event(self, widget, data=None):
		self.edit_error_window.hide()
		return True

	def on_button_error_main_ok_clicked(self, widget, data=None):
		self.error_main_window.hide()

	def on_error_main_window_delete_event(self, widget, data=None):
		self.error_main_window.hide()
		return True

	def __init__(self):
		builder = gtk.Builder()
		if os.path.exists('gtkhostsetup.glade'):
			builder.add_from_file('gtkhostsetup.glade')
		elif os.path.exists('/usr/share/salixtools/gtkhostsetup/gtkhostsetup.glade'):
			builder.add_from_file('/usr/share/salixtools/gtkhostsetup/gtkhostsetup.glade')
		self.window = builder.get_object('gtkhostsetup')


		#
		# Main window
		#
		self.entry_hostname = builder.get_object('entry_hostname')
		self.entry_domain = builder.get_object('entry_domain')
		current_hostname = get_hostname()
		self.entry_hostname.set_text(current_hostname[0])
		self.entry_domain.set_text(current_hostname[1])

		self.treeviewcolumn_ip = builder.get_object('treeviewcolumn_ip')
		self.treeviewcolumn_hostname = builder.get_object('treeviewcolumn_hostname')
		self.treeviewcolumn_domain = builder.get_object('treeviewcolumn_domain')
		self.treeviewcolumn_ip.set_title(_('IP address'))
		self.treeviewcolumn_hostname.set_title(_('Hostname'))
		self.treeviewcolumn_domain.set_title(_('Domain'))

		self.treeview_hosts = builder.get_object('treeview_hosts')
		self.liststore_hosts = builder.get_object('liststore_hosts')
		self.liststore_hosts.clear()
		self.create_host_list(self)

		#
		# Add host window
		#
		self.add_host_window = builder.get_object('add_host_window')
		self.entry_new_ip = builder.get_object('entry_new_ip')
		self.entry_new_hostname = builder.get_object('entry_new_hostname')
		self.entry_new_domain = builder.get_object('entry_new_domain')


		#
		# Edit host window
		#
		self.edit_host_window = builder.get_object('edit_host_window')
		self.entry_edit_ip = builder.get_object('entry_edit_ip')
		self.entry_edit_hostname = builder.get_object('entry_edit_hostname')
		self.entry_edit_domain = builder.get_object('entry_edit_domain')

		#
		# Error message in main window
		#
		self.error_main_window = builder.get_object('error_main_window')
		self.label_main_error = builder.get_object('label_main_error')
		
		#
		# Error message in add window
		#
		self.add_error_window = builder.get_object('add_error_window')
		self.label_add_error = builder.get_object('label_add_error')

		#
		# Error message in edit window
		#
		self.edit_error_window = builder.get_object('edit_error_window')
		self.label_edit_error = builder.get_object('label_edit_error')
		
		#
		# About dialog
		#
		self.aboutdialog = builder.get_object('aboutdialog')

		builder.connect_signals(self)

if __name__ == "__main__":
	app = GTKHostSetup()
	app.window.show()
	gtk.main()
