#!/usr/bin/python import logging import os import string import subprocess try: import glib import gobject import dbus import dbus.service import dbus.mainloop.glib except ImportError, e: sys.stderr.write("Failed to import '%s', can not use dbus" % e) sys.exit(1) class PermissionDeniedError(dbus.DBusException): " permission denied by policy " pass class AptXapianIndexDBusService(dbus.service.Object): DBUS_INTERFACE_NAME = "org.debian.AptXapianIndex" def __init__(self): bus_name = dbus.service.BusName(self.DBUS_INTERFACE_NAME, bus=dbus.SystemBus()) dbus.service.Object.__init__(self, bus_name, '/') self._active_axi = None def _authWithPolicyKit(self, sender, connection, priv): system_bus = dbus.SystemBus() obj = system_bus.get_object("org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority") policykit = dbus.Interface(obj, "org.freedesktop.PolicyKit1.Authority") info = dbus.Interface(connection.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus/Bus', False), 'org.freedesktop.DBus') pid = info.GetConnectionUnixProcessID(sender) subject = ('unix-process', { 'pid' : dbus.UInt32(pid, variant_level=1), 'start-time' : dbus.UInt64(0, variant_level=1), } ) details = { '' : '' } flags = dbus.UInt32(1) # AllowUserInteraction = 0x00000001 cancel_id = '' (ok, notused, details) = policykit.CheckAuthorization( subject, priv, details, flags, cancel_id) return ok @dbus.service.signal(dbus_interface=DBUS_INTERFACE_NAME, signature="b") def UpdateFinished(self, res): logging.debug("Emitting UpdateFinished: %s" % res) @dbus.service.signal(dbus_interface=DBUS_INTERFACE_NAME, signature="i") def UpdateProgress(self, percent): logging.debug("Emitting UpdateProgress: %s" % percent) def _update_apt_xapian_index(self, cmd): p = subprocess.Popen(cmd, stdout=subprocess.PIPE) self._active_axi = p while True: while gobject.main_context_default().pending(): gobject.main_context_default().iteration() res = p.poll() if res is not None: break line = p.stdout.readline().strip() if not line: continue try: (op, progress) = string.split(line, sep=":", maxsplit=1) if op == "progress": percent = int(progress.split("/")[0]) self.UpdateProgress(percent) except ValueError: pass # axi finished self._active_axi = None # emit finish signal self.UpdateFinished(res == 0) @dbus.service.method(DBUS_INTERFACE_NAME, in_signature='bb', out_signature='', sender_keyword='sender', connection_keyword='conn') def update_async(self, force, update_only, sender=None, conn=None): if not self._authWithPolicyKit(sender, conn, "org.debian.aptxapianindex.update"): raise PermissionDeniedError, "Permission denied by policy" # do not start update-apt-xapian-index twice, the clients will # get the finished signal from the previous running one if self._active_axi: return cmd = ["/usr/sbin/update-apt-xapian-index", "--batch-mode"] if force: cmd.append("--force") if update_only: cmd.append("--update") glib.timeout_add(100, self._update_apt_xapian_index, cmd) if __name__ == "__main__": dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) server = AptXapianIndexDBusService() gobject.MainLoop().run()