Project

General

Profile

« Previous | Next » 

Revision 0b45b84e

Added by dsorber almost 9 years ago

pwmgr v0.4.0 -- Added save warning before quit dialog. Added improved state tracking. Finally, added progress pop on close to give user feedback while ramdisk cleanup is happening.

View differences:

software/pwmgr/pwmgr.py
import shutil
import subprocess
import sys
import time
import threading
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Pango, Gdk
from gi.repository import Gtk, Pango, Gdk, GLib
MOUNT_PATH = '/mnt/pw_ramdisk'
PWD_FILE_PATH = '/home/dsorber/Desktop/network'
......
ENC_TMP_FILE_PATH = '/home/dsorber/Documents/chicken_soup.enc.tmp'
KEY_FILE_PATH = '/mnt/pw_ramdisk/.f05d11ef-000c-45c2-ae14-56b56c23e1c5'
VERSION = '0.0.3'
VERSION = '0.0.4'
class SearchDialog(Gtk.Dialog):
......
self.show_all()
class WarningDialog(Gtk.Dialog):
class WarningDialog(Gtk.MessageDialog):
def __init__(self, parent, title, message):
Gtk.MessageDialog.__init__(self, parent,
......
message)
self.set_title(title)
# Make hitting ENTER trigger the OK button
ok_button = self.get_widget_for_response(response_id=Gtk.ResponseType.OK)
ok_button.set_can_default(True)
ok_button.grab_default()
self.show_all()
def get_user_pw(parent, message, title=''):
......
dialog.set_title(title)
box = dialog.get_content_area()
box.set_border_width(10)
pw_entry = Gtk.Entry()
pw_entry.set_visibility(False)
pw_entry.set_invisible_char('*')
......
if (response == Gtk.ResponseType.OK) and (text != ''):
return text
else:
return None
return None
class ProgressBarWindow(Gtk.Window):
def __init__(self, parent, title):
Gtk.Window.__init__(self, title=title)
self.set_border_width(10)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3)
self.add(vbox)
self.progressbar = Gtk.ProgressBar()
vbox.pack_start(self.progressbar, True, True, 0)
self.progressbar.set_text('Zee text')
self.progressbar.set_show_text(True)
self.set_modal(True)
#~ self.set_decorated(False)
self.set_deletable(False)
self.set_transient_for(parent)
def update_text(self, text):
self.progressbar.set_text(text)
def update_complete(self, fraction):
self.progressbar.set_fraction(fraction)
class TextViewWindow(Gtk.Window):
......
self.mounted = False
self.pass_data_loaded = False
self.pwd_file_fd = None
self.pbar_win = None
self.should_quit = False
def async_quit(self):
if self.should_quit:
if self.pbar_win is not None:
self.pbar_win.destroy()
Gtk.main_quit()
print('REAL QUIT')
return True
def _key_press_event(self, widget, event):
keyval = event.keyval
......
"""
# Get password
passwd = get_user_pw(self, 'Please enter your password', 'Password')
if passwd is None:
return
if not self.pass_data_loaded:
passwd = get_user_pw(self, 'Please enter your password', 'Password')
if passwd is None:
return
if not self.mounted:
os.makedirs(MOUNT_PATH, 0o600, exist_ok=True)
......
self.textbuffer.set_text(pwd_file_fd.read())
self.textview.set_editable(True)
self.textview.set_cursor_visible(True)
# Mark state that pasword data is loaded
self.pass_data_loaded = True
def save_pwd_file(self, widget):
"""
Save handler
"""
if self.mounted:
if self.mounted and self.pass_data_loaded:
# Write the password store datat to the sratch file
with open(SCRATCH_FILE_PATH, 'w') as pwd_file_fd:
......
self.textbuffer.set_text('')
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
# Mark password data as not loaded
self.pass_data_loaded = False
def _remove_mount_files(self):
# Remove files in the mount path
for file_ in glob.glob('{:s}/*'.format(MOUNT_PATH)):
os.remove(file_)
def close_pwd_file(self, widget, other):
def do_mount_cleanup(self):
"""
Close handler
Clean up ramdisk by overwriting, then unmount
"""
GLib.idle_add(self.pbar_win.update_text, 'Starting ramdisk cleanup')
#~ dialog = WarningDialog(self, 'Close?', 'Have you saved?')
#~ response = dialog.run()
#~ dialog.destroy()
# Clear the buffer and disable the textview
self.textbuffer.set_text('')
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
rand_write_cmd = 'dd if=/dev/urandom of={:s} bs=16M count=1 status=none'
rand_write_cmd = rand_write_cmd.format(os.path.join(MOUNT_PATH, 'data'))
zero_write_cmd = 'dd if=/dev/zero of={:s} bs=16M count=1 status=none'
zero_write_cmd = zero_write_cmd.format(os.path.join(MOUNT_PATH, 'data'))
if self.mounted:
self._remove_mount_files()
# Overwrite the ramdisk a few times
for ctr in range(10):
print(ctr)
message = 'Overwrite {:d} of 10'.format(ctr + 1)
GLib.idle_add(self.pbar_win.update_text, message)
subprocess.call(rand_write_cmd, shell=True, timeout=5)
self._remove_mount_files()
subprocess.call(zero_write_cmd, shell=True, timeout=5)
self._remove_mount_files()
# Overwrite a few times
for ctr in range(10):
print(ctr)
subprocess.call(rand_write_cmd, shell=True, timeout=5)
self._remove_mount_files()
subprocess.call(zero_write_cmd, shell=True, timeout=5)
self._remove_mount_files()
GLib.idle_add(self.pbar_win.update_complete, (ctr + 1) / 10)
GLib.idle_add(self.pbar_win.update_text, 'Unmounting ramdisk')
umount_cmd = 'umount {:s}'.format(MOUNT_PATH)
subprocess.call(umount_cmd, shell=True, timeout=5)
GLib.idle_add(self.pbar_win.update_text, 'Complete')
self.should_quit = True
print('SET should quit')
def close_pwd_file(self, widget, other):
"""
Close handler
"""
# If data is loaded ask to save before closing
if self.pass_data_loaded:
dialog = WarningDialog(self, 'Save changes?',
'Save changes to password data?')
response = dialog.run()
dialog.destroy()
if response == Gtk.ResponseType.OK:
self.save_pwd_file(widget)
# Clear the buffer and disable the textview
self.textbuffer.set_text('')
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
if self.mounted:
# Start async polling of the quit flag
GLib.idle_add(self.async_quit)
# Create the progress window
self.pbar_win = ProgressBarWindow(self, 'Closing...')
self.pbar_win.show_all()
umount_cmd = 'umount {:s}'.format(MOUNT_PATH)
subprocess.call(umount_cmd, shell=True, timeout=5)
# Start the work thread that does the cleanup
thread = threading.Thread(target=self.do_mount_cleanup)
thread.start()
else:
Gtk.main_quit()
Gtk.main_quit()
print('CLOSE')
def on_button_clicked(self, widget, tag):
bounds = self.textbuffer.get_selection_bounds()
if len(bounds) != 0:
start, end = bounds
self.textbuffer.apply_tag(tag, start, end)
def on_clear_clicked(self, widget):
start = self.textbuffer.get_start_iter()
end = self.textbuffer.get_end_iter()

Also available in: Unified diff