Commits

Thomas Gläßle committed f54092f

Separate password prompt from mount logic

Enable user defined password prompt.

  • Participants
  • Parent commits 90a3cac

Comments (0)

Files changed (2)

File udiskie/mount.py

 import udiskie.device
 import udiskie.match
 import udiskie.notify
+import udiskie.prompt
 
 class DeviceState:
     def __init__(self, mounted, has_media):
 class AutoMounter:
     CONFIG_PATH = 'udiskie/filters.conf'
 
-    def __init__(self, bus=None, filter_file=None, notify=None):
+    def __init__(self, bus=None, filter_file=None, notify=None, prompt=None):
         self.log = logging.getLogger('udiskie.mount.AutoMounter')
         self.last_device_state = {}
 
         else:
             self.notify = lambda ctx: getattr(notify, ctx)
 
+        if not prompt:
+            self.prompt = lambda text, title: None
+        else:
+            self.prompt = prompt
+
+
         self.bus.add_signal_receiver(self.device_added,
                                      signal_name='DeviceAdded',
                                      bus_name='org.freedesktop.UDisks')
             if device.is_unlocked():
                 return
 
-
-            from distutils.spawn import find_executable
-            import subprocess
-
-            # enter password via zenity
-            zenity = find_executable('zenity')
-            if zenity is None:
-                return
-
-            try:
-                password = subprocess.check_output([zenity,
-                    '--entry', '--hide-text',
-                    '--title', 'Unlock encrypted device',
-                    '--text', 'Enter password for %s:' % (device,) ])
-                password = password.rstrip('\n')
-            except subprocess.CalledProcessError, exc:
-                # User pressed cancel
+            # prompt user for password
+            password = self.prompt(
+                    'Enter password for %s:' % (device,),
+                    'Unlock encrypted device')
+            if password is None:
                 return
 
             # unlock device
                 device.unlock(password, [])
                 self.log.info('unlocked device %s' % (device,))
             except dbus.exceptions.DBusException, dbus_err:
-                self.log.error('failed to unlock device %s: %s'
+                self.log.error('failed to unlock device %s:\n%s'
                                             % (device, dbus_err))
-                self.notify('unlock')('Failed to unlock %s' % (device,),
-                        'DBusException: %s\n' % (dbus_err,)
-                        + 'Try\n\tudisksctl unlock -b <device>')
                 return
 
             self.notify('unlock')(device.device_file())
     parser.add_option('-s', '--suppress', action='store_true',
                       dest='suppress_notify', default=False,
                       help='suppress popup notifications')
+    parser.add_option('-P', '--password-prompt', action='store',
+                      dest='password_prompt', default='zenity',
+                      metavar='MODULE', help="replace password prompt")
     (options, args) = parser.parse_args(args)
 
     log_level = logging.INFO
     else:
         notify = udiskie.notify.Notify('udiskie.mount')
 
+    prompt = udiskie.prompt.password(options.password_prompt)
 
-    mounter = AutoMounter(bus=None, filter_file=options.filters, notify=notify)
+    mounter = AutoMounter(
+            bus=None, filter_file=options.filters,
+            notify=notify, prompt=prompt)
     mounter.mount_present_devices()
     return gobject.MainLoop().run()

File udiskie/prompt.py

+import importlib
+import subprocess
+from distutils.spawn import find_executable
+
+
+def password(prompt_name):
+    """
+    Create a password prompt function.
+    """
+    if not prompt_name:
+        return None
+
+    executable = find_executable(prompt_name)
+    if executable is None:
+        return None
+
+    # builtin variant: enter password via zenity:
+    if prompt_name == 'zenity':
+        def doprompt(text, title):
+            return subprocess.check_output([executable,
+                '--entry', '--hide-text',
+                '--text', text, '--title', title ])
+
+    # builtin variant: enter password via systemd-ask-password:
+    elif prompt_name == 'systemd-ask-password':
+        def doprompt(text, title):
+            return subprocess.check_output([executable, text])
+
+    # enter password via user supplied binary:
+    else:
+        def doprompt(text, title):
+            return subprocess.check_output([executable, text, title])
+
+    def password_prompt(text, title):
+        try:
+            return doprompt(text, title).rstrip('\n')
+        except subprocess.CalledProcessError:
+            return None
+
+    return password_prompt