from Tkinter import *
from tkMessageBox import *
from Tix import *
+ from ScrolledText import *
def input_string (prompt=""):
return raw_input (prompt)
from tkinter import *
from tkinter.messagebox import *
from tkinter.tix import *
+ from tkinter.scrolledtext import *
def input_string (prompt=""):
return input (prompt)
return textwrap.fill (ldedented (text), width = 72)
-def read_input_string (prompt="", default=""):
+def read_input_string (prompt = "", default = ""):
if default != "":
readline.set_startup_hook (lambda: readline.insert_text (default))
dest = "gui",
action = "store_false",
help = "Disable GUI, use text mode.")
- gnupg_group = parser.add_argument_group ("GnuPG",
+ gnupg_group = parser.add_argument_group (
+ "GnuPG",
"Options related to the GnuPG setup.")
gnupg_group.add_argument (
"--no-gpg",
gnupg_group.add_argument (
"--gpg-home",
dest = "gnupg_home",
- default = "~/.gnupg",
+ default = os.getenv("GNUPGHOME") or "~/.gnupg",
metavar = "PATH",
help = "Default directory for GnuPG files.")
- openssh_group = parser.add_argument_group ("OpenSSH",
+ openssh_group = parser.add_argument_group (
+ "OpenSSH",
"Options related to the OpenSSH setup.")
openssh_group.add_argument (
"--no-ssh",
else:
del batch_env["DISPLAY"]
- batch_passphrase += "GET_PASSPHRASE --data --check --qualitybar X X Passphrase X\n"
+ batch_passphrase += \
+ "GET_PASSPHRASE --data --check --qualitybar X X Passphrase X\n"
passphrase_process = subprocess.Popen (["gpg-agent", "--server"],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
env = batch_env)
- (stdout, stderr) = passphrase_process.communicate (batch_passphrase)
+ (stdout, stderr) = passphrase_process.communicate (batch_passphrase.encode ("UTF-8"))
if passphrase_process.returncode != 0:
raise Exception ("Couldn't read passphrase.")
for line in stdout.splitlines ():
- if line.startswith ("D "):
+ if line.decode ("UTF-8").startswith ("D "):
return line[2:]
return ""
if comment != "":
batch_key += "Name-Comment: {}\n".format (comment)
- tmp.write (batch_key)
+ tmp.write (batch_key.encode ("UTF-8"))
tmp.flush ()
batch_env = dict (os.environ)
gnupg_process = subprocess.Popen (["gpg2",
"--homedir", gnupg_home,
"--batch", "--gen-key", tmp.name],
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.STDOUT,
env = batch_env)
- gnupg_process.wait ()
+
+ # TODO: argh. there has to be a better way
+ gnupg_process.stdin.close ()
+ while gnupg_process.poll () is None:
+ sys.stdout.write (gnupg_process.stdout.readline ())
+
+ while True:
+ line = gnupg_process.stdout.readline ()
+ if len (line) == 0:
+ break
+ sys.stdout.write (line.decode ("UTF-8"))
if gnupg_process.returncode != 0:
raise Exception ("Couldn't create GnuPG key.")
print ("Creating OpenSSH directory at '{}'.".format (openssh_home))
ensure_directories (openssh_home, 0o700)
- print ("Creating OpenSSH configuration at '{}'.".format (openssh_config))
+ print ("Creating OpenSSH configuration at '{}'."
+ .format (openssh_config))
with open (openssh_config, "w") as config:
config.write (ldedented ("""
ForwardAgent yes
print ("OpenSSH key already exists at '{}'.".format (openssh_key))
return
+ openssh_key_dsa = os.path.join (openssh_home, "id_dsa")
+
+ if os.path.exists (openssh_key_dsa):
+ print ("OpenSSH key already exists at '{}'.".format (openssh_key_dsa))
+ return
+
print (filled ("No OpenSSH key available. Generating new key."))
if not arguments.gui:
passphrase = input_passphrase (arguments)
+ batch_env = dict (os.environ)
+ if not arguments.gui:
+ del batch_env["DISPLAY"]
+
# TODO: is it somehow possible to pass the password on stdin?
openssh_process = subprocess.Popen (["ssh-keygen",
"-P", passphrase,
"-C", comment,
- "-f", openssh_key])
- openssh_process.wait ()
+ "-f", openssh_key],
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.STDOUT,
+ env = batch_env)
+
+ # TODO: argh. there has to be a better way
+ openssh_process.stdin.close ()
+ while openssh_process.poll () is None:
+ sys.stdout.write (openssh_process.stdout.readline ())
+
+ while True:
+ line = openssh_process.stdout.readline ()
+ if len (line) == 0:
+ break
+ sys.stdout.write (line.decode ("UTF-8"))
if openssh_process.returncode != 0:
raise Exception ("Couldn't create OpenSSH key.")
+# http://www.blog.pythonlibrary.org/2014/07/14/tkinter-redirecting-stdout-stderr/
+class RedirectText (object):
+ def __init__ (self, widget):
+ self.widget = widget
+
+ def write (self, string):
+ self.widget.insert (END, string)
+
+
+class CryptoInstallProgress (Toplevel):
+ def __init__ (self):
+ Toplevel.__init__ (self)
+
+ self.create_widgets ()
+
+ def create_widgets (self):
+ self.balloon = Balloon (self, initwait = 250)
+
+ self.text = ScrolledText (self)
+ self.text.pack (fill = BOTH, expand = True)
+
+ self.redirect = RedirectText (self.text)
+
+ self._quit = Button (self)
+ self._quit["text"] = "Quit"
+ self._quit["command"] = self.quit
+ self.balloon.bind_widget (self._quit,
+ msg = "Quit the program immediately")
+ self._quit.pack ()
+
+
class CryptoInstall (Tk):
def __init__ (self, arguments):
Tk.__init__ (self)
self.create_widgets ()
-
def create_widgets (self):
self.balloon = Balloon (self, initwait = 250)
-
self.info_frame = Frame (self)
self.info_frame.pack (fill = X)
-
self.user_label = Label (self.info_frame)
self.user_label["text"] = "Username"
self.user_label.grid ()
"""))
self.user.grid (row = 0, column = 1)
-
self.host_label = Label (self.info_frame)
self.host_label["text"] = "Host Name"
self.host_label.grid ()
"""))
self.host.grid (row = 1, column = 1)
-
self.name_label = Label (self.info_frame)
self.name_label["text"] = "Full Name"
self.name_label.grid ()
"""))
self.name.grid (row = 2, column = 1)
-
self.email_label = Label (self.info_frame)
self.email_label["text"] = "Email address"
self.email_label.grid ()
"""))
self.email.grid (row = 3, column = 1)
-
self.comment_label = Label (self.info_frame)
self.comment_label["text"] = "Comment phrase"
self.comment_label.grid ()
"""))
self.comment.grid (row = 4, column = 1)
-
self.options_frame = Frame (self)
self.options_frame.pack (fill = X)
self.gnupg_var.set (1 if self.arguments.gnupg else 0)
self.gnupg_var.trace ("w", self.update_widgets)
- self.gnupg = Checkbutton (self.options_frame, variable = self.gnupg_var)
+ self.gnupg = Checkbutton (self.options_frame,
+ variable = self.gnupg_var)
self.gnupg.grid (row = 0, column = 1)
self.openssh_label = Label (self.options_frame)
variable = self.openssh_var)
self.openssh.grid (row = 1, column = 1)
-
self.button_frame = Frame (self)
self.button_frame.pack (fill = X)
self._generate = Button (self.button_frame)
self._generate["text"] = "Generate Keys"
self._generate["command"] = self.generate
- self.balloon.bind_widget (self._generate,
- msg = "Generate the keys as configured above")
+ self.balloon.bind_widget (
+ self._generate,
+ msg = "Generate the keys as configured above")
self._generate.pack (side = LEFT, fill = Y)
self._quit = Button (self.button_frame)
self.update_widgets ()
-
def valid_state (self):
if not self.openssh_var.get () and not self.gnupg_var.get ():
return False
return True
-
def update_widgets (self, *args):
valid = self.valid_state ()
self.balloon.bind_widget (self.openssh, msg = msg)
self.balloon.bind_widget (self.openssh_label, msg = msg)
-
def generate (self):
- # TODO: capture and show stdout and stderr
- if self.gnupg_var.get ():
- gnupg_setup (self.arguments,
- self.name_var.get (),
- self.email_var.get (),
- self.comment_var.get ())
-
- if self.openssh_var.get ():
- comment = "{}@{}".format (self.user_var.get (),
- self.host_var.get ())
- openssh_setup (self.arguments, comment)
+ progress = CryptoInstallProgress ()
- # TODO: show summary before exiting
- self.quit ()
+ stdout = sys.stdout
+ try:
+ sys.stdout = progress.redirect
+ # TODO: capture and show stdout and stderr
+ if self.gnupg_var.get ():
+ gnupg_setup (self.arguments,
+ self.name_var.get (),
+ self.email_var.get (),
+ self.comment_var.get ())
+ self.update_widgets ()
-# TODO: use gtk instead? would be more consistent with the pinentry style
-# (assuming it's using gtk)
-def gui (arguments):
- app = CryptoInstall (arguments)
- app.mainloop ()
+ if self.openssh_var.get ():
+ comment = "{}@{}".format (self.user_var.get (),
+ self.host_var.get ())
+ openssh_setup (self.arguments, comment)
+ self.update_widgets ()
+ finally:
+ sys.stdout = stdout
def main ():
arguments = parse_arguments ()
if arguments.gui:
- gui (arguments)
+ # TODO: use gtk instead? would be more consistent with the pinentry style
+ # (assuming it's using gtk)
+ CryptoInstall (arguments).mainloop ()
else:
if arguments.gnupg:
gnupg_setup (arguments)