#!/usr/bin/env python
#

from gi.repository import Gtk, GObject, GLib, Gdk
import subprocess
import os
import sys
import threading
import getopt
import signal
import string
import random

global interface
global diskcrypt

class CreateSDCard(object):
	builder = None
	msg = None
	show = False

	def __init__(self):
		global interface
		global diskcrypt

		self.builder = Gtk.Builder()
		self.builder.add_from_file("create_sdcard.glade")
		self.builder.connect_signals(self)

		self.window = self.builder.get_object("mainWindow")
		self.window.set_title("Decrypt disk boot setup")
		self.window.connect("delete-event", Gtk.main_quit)

		self.window.show()
		self.builder.get_object("label11").set_text(interface)

		diskcrypt = None

                for i in range(1, 21):
                    try:
                        ret = subprocess.check_output("cryptsetup luksDump /dev/sda{} 2> /dev/null".format(str(i)), shell=True)
                        if len(ret) == None:
			    diskcrypt = None
                        else:
                            diskcrypt = "/dev/sda" + str(i)
                            break
                    except:
                        diskcrypt = None

		if diskcrypt == None:
		    self.builder.get_object("label1").set_text("\nThe boot disk is not crypted\nor you are not the root user.")
		    self.builder.get_object("label6").set_sensitive(False)
                    self.builder.get_object("label10").set_sensitive(False)
		    self.builder.get_object("label11").set_sensitive(False)
		    self.builder.get_object("entry1").set_sensitive(False)
		    self.builder.get_object("checkbutton1").set_sensitive(False)
		    self.builder.get_object("button2").set_sensitive(False)
		else:
		    self.builder.get_object("label1").set_text("\nThe " + diskcrypt + " boot disk is\ncrypted and mounted on /.")
		    self.msg = "\nThe " + diskcrypt + " boot disk is\ncrypted and mounted on /."

		return

	def show_password(self, args):
		if self.show == False:
			self.builder.get_object("entry1").set_visibility(True)
			self.show = True
		else:
			self.builder.get_object("entry1").set_visibility(False)
			self.show = False

	def sdcancel(self, *args):
		Gtk.main_quit()

	def do_gui(self, function, *args, **kw):
        	def idle_func():
            		Gdk.threads_enter()
            		try:
                		while Gtk.events_pending():
                    			Gtk.main_iteration()
                		function(*args, **kw)
                		return False
            		finally:
                		Gdk.threads_leave()
            	GObject.idle_add(idle_func, priority=GObject.PRIORITY_DEFAULT)

	def sdcontinue(self, *args):
                self.builder.get_object("label6").set_sensitive(False)
                self.builder.get_object("entry1").set_sensitive(False)
		self.builder.get_object("checkbutton1").set_sensitive(False)
                self.builder.get_object("button1").set_sensitive(False)
                self.builder.get_object("button2").set_sensitive(False)

		self.builder.get_object("label1").set_text("\nDecrypt disk boot setup in progress... ")

		if self.show == True:
			self.builder.get_object("checkbutton1").set_active(False)

		self.timeout = GObject.timeout_add(100, self.sdstart, None)

	def sdstart(self, *args):
		global interface
		global diskcrypt

		if len(self.builder.get_object("entry1").get_text()) == 0 or self.builder.get_object("entry1").get_text() == None:
			self.dialog1 = self.builder.get_object("messagedialog1")
			Gdk.threads_enter()
	                self.response1 = self.dialog1.run()
			Gdk.threads_leave()
	                if self.response1 == Gtk.ResponseType.OK:
	                	self.do_gui(self.dialog1.hide)
				self.builder.get_object("label1").set_text(self.msg)
		                self.builder.get_object("label6").set_sensitive(True)
		                self.builder.get_object("entry1").set_sensitive(True)
				self.builder.get_object("checkbutton1").set_sensitive(True)
		                self.builder.get_object("button1").set_sensitive(True)
		                self.builder.get_object("button2").set_sensitive(True)
				return False

		passphrase = self.builder.get_object("entry1").get_text()
		subprocess.call("rm -f /tmp/passphrase 2> /dev/null", shell=True)
		f = open('/tmp/passphrase', 'a')
		f.write(passphrase)
		f.close()

		try:
			subprocess.check_output("cryptsetup --key-file=/tmp/passphrase luksKillSlot {} 5".format(diskcrypt), shell=True)
		except subprocess.CalledProcessError as e:
			if e.returncode == 1:
				pass
			else:
				self.dialog1 = self.builder.get_object("messagedialog1")
				Gdk.threads_enter()
                        	self.response1 = self.dialog1.run()
				Gdk.threads_leave()
                        	if self.response1 == Gtk.ResponseType.OK:
                        	        self.do_gui(self.dialog1.hide)
					subprocess.call("rm -f /tmp/passphrase 2> /dev/null", shell=True)
					self.builder.get_object("label1").set_text(self.msg)
					self.builder.get_object("entry1").set_text("")
			                self.builder.get_object("label6").set_sensitive(True)
			                self.builder.get_object("entry1").set_sensitive(True)
					self.builder.get_object("checkbutton1").set_sensitive(True)
			                self.builder.get_object("button1").set_sensitive(True)
			                self.builder.get_object("button2").set_sensitive(True)
                        	        return False

		subprocess.call("rm -f {}passphrase 2> /dev/null".format(interface), shell=True)
		passfile = interface + "passphrase"
		f = open(passfile, 'a')
		f.write(str(random.random()))
		f.close()

		try:
			subprocess.check_output("cryptsetup --key-file=/tmp/passphrase --key-slot 5 luksAddKey {} {}passphrase".format(diskcrypt, interface), shell=True)
		except:
			self.dialog1 = self.builder.get_object("messagedialog1")
			Gdk.threads_enter()
                        self.response1 = self.dialog1.run()
			Gdk.threads_leave()
                        if self.response1 == Gtk.ResponseType.OK:
    	                	self.do_gui(self.dialog1.hide)
				subprocess.call("rm -f /tmp/passphrase 2> /dev/null", shell=True)
	                        subprocess.call("rm -f {}passphrase 2> /dev/null".format(interface), shell=True)
				self.builder.get_object("label1").set_text(self.msg)
				self.builder.get_object("entry1").set_text("")
                                self.builder.get_object("label6").set_sensitive(True)
                                self.builder.get_object("entry1").set_sensitive(True)
				self.builder.get_object("checkbutton1").set_sensitive(True)
                                self.builder.get_object("button1").set_sensitive(True)
                                self.builder.get_object("button2").set_sensitive(True)
                        	return False

		self.dialog2 = self.builder.get_object("messagedialog2")
		Gdk.threads_enter()
                self.response2 = self.dialog2.run()
		Gdk.threads_leave()
                if self.response2 == Gtk.ResponseType.OK:
                	self.do_gui(self.dialog2.hide)
			subprocess.call("rm -f /tmp/passphrase", shell=True)
			self.builder.get_object("label1").set_text(self.msg)
                        self.builder.get_object("label6").set_sensitive(True)
                        self.builder.get_object("entry1").set_sensitive(True)
			self.builder.get_object("checkbutton1").set_sensitive(True)
                        self.builder.get_object("button1").set_sensitive(True)
                        self.builder.get_object("button2").set_sensitive(True)
                       	Gtk.main_quit() 

		return False

def usage():
        print " "
        print "  Automatically decrypt disk boot setup usage:"
        print " "
	print "  -i <Interface>   : The SD Card interface absolute mount path"
        print " "
        sys.exit()

        return

def signal_handler(signum, frame):
	print "[ crsd_card][00000000] Signal caught."
        sys.exit()

        return

def main():
	global interface

        try:
                opts, args = getopt.getopt(sys.argv[1:],"i:")
        except:
                usage()
                sys.exit(1)

	interface = None

        for o, a in opts:
		if o == '-i':
			interface = a

        if interface == None:
                usage()
                sys.exit(1)

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

	app = CreateSDCard()
	Gtk.main()

	return

if __name__ == "__main__":
	main()
