diff options
author | Vincent Untz <vuntz@novell.com> | 2008-09-22 05:18:03 +0200 |
---|---|---|
committer | Vincent Untz <vuntz@novell.com> | 2008-09-22 05:18:03 +0200 |
commit | 8f4dd9428983f7a98c5c500a87b8f1f50a6e3814 (patch) | |
tree | 00f2a12116d6942ac0e581b4de5ddb5162d27626 | |
parent | 30b23465704727a89cfcc2d0e8c9e2225d220d77 (diff) |
Improve s-c-p patch (UI not blocking, no repeating password dialogs)cups-pk-helper-0.0.1
And pass distcheck.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | patches/system-config-printer.patch | 177 | ||||
-rw-r--r-- | po/ChangeLog | 0 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/test-cups-pk.c | 4 | ||||
-rwxr-xr-x | src/test-cups-pk.py | 2 |
6 files changed, 146 insertions, 39 deletions
@@ -1,5 +1,6 @@ *.sw[nop] *.o +*.tar.* INSTALL Makefile Makefile.in diff --git a/patches/system-config-printer.patch b/patches/system-config-printer.patch index 7e26f38..d3fd6e1 100644 --- a/patches/system-config-printer.patch +++ b/patches/system-config-printer.patch @@ -1,5 +1,5 @@ diff --git a/authconn.py b/authconn.py -index 6244eee..4fff0d1 100644 +index 6244eee..ad3bfb0 100644 --- a/authconn.py +++ b/authconn.py @@ -18,6 +18,7 @@ @@ -27,12 +27,15 @@ index 6244eee..4fff0d1 100644 port=self._port, encryption=self._encryption) except TypeError: -@@ -129,16 +137,17 @@ class Connection: +@@ -129,16 +137,20 @@ class Connection: cups.setServer (self._server) cups.setPort (self._port) cups.setEncryption (self._encryption) - self._connection = cups.Connection () + self._connection = create_object () ++ ++ if self._use_pk: ++ self._connection.set_parent(self._parent) self._user = self._use_user debugprint ("Connected as user %s" % self._user) @@ -48,15 +51,46 @@ index 6244eee..4fff0d1 100644 continue setattr (self, fname, self._make_binding (fname, fn)) +@@ -164,6 +176,8 @@ class Connection: + raise cups.IPPError (cups.IPP_NOT_AUTHORIZED, '') + break + except cups.IPPError, (e, m): ++ if self._use_pk and m == 'pkcancel': ++ raise + if not self._cancel and (e == cups.IPP_NOT_AUTHORIZED or + e == cups.IPP_FORBIDDEN): + self._failed () diff --git a/cupspk.py b/cupspk.py new file mode 100644 -index 0000000..b5d9e7f +index 0000000..a72fc59 --- /dev/null +++ b/cupspk.py -@@ -0,0 +1,365 @@ -+# TODO: UI is blocking. We should do the dbus call async and stay stuck in our main loop +@@ -0,0 +1,454 @@ ++# vim: set ts=4 sw=4 et: coding=UTF-8 ++# ++# Copyright (C) 2008 Novell, Inc. ++# ++# Authors: Vincent Untz ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++# ++ ++# check FIXME/TODO here +# check FIXME/TODO in cups-pk-helper +# define fine-grained policy (more than one level of permission) ++# add missing methods + +import os + @@ -64,6 +98,10 @@ index 0000000..b5d9e7f + +import cups +import dbus ++import gtk ++ ++from dbus.mainloop.glib import DBusGMainLoop ++DBusGMainLoop(set_as_default=True) + +PK_AUTH_NAME = 'org.freedesktop.PolicyKit.AuthenticationAgent' +PK_AUTH_PATH = '/' @@ -75,11 +113,33 @@ index 0000000..b5d9e7f + +CUPS_PK_NEED_AUTH = 'org.opensuse.CupsPkHelper.Mechanism.NotPrivileged' + ++ ++pk_auth_ret = False ++pk_auth_error = None ++pk_auth_running = False ++pk_auth_done = False ++ ++def _pk_auth_reply_handler(ret): ++ global pk_auth_ret ++ global pk_auth_done ++ ++ pk_auth_ret = ret ++ pk_auth_done = True ++ ++def _pk_auth_error_handler(e): ++ global pk_auth_error ++ global pk_auth_done ++ ++ pk_auth_error = str(e) ++ pk_auth_done = True ++ ++ +# we can't subclass cups.Connection, even when adding +# Py_TPFLAGS_BASETYPE to cupsconnection.c +# So we'll hack this... +class Connection: + def __init__(self, host, port, encryption): ++ self._parent = None + self._session_bus = dbus.SessionBus() + self._system_bus = dbus.SystemBus() + @@ -104,6 +164,10 @@ index 0000000..b5d9e7f + setattr(self, fname, fn.__call__) + + ++ def set_parent(self, parent): ++ self._parent = parent ++ ++ + def _get_cups_pk(self): + try: + object = self._system_bus.get_object(CUPS_PK_NAME, CUPS_PK_PATH) @@ -113,15 +177,41 @@ index 0000000..b5d9e7f + + + def _obtain_auth(self, action, xid = 0): ++ global pk_auth_ret ++ global pk_auth_error ++ global pk_auth_done ++ global pk_auth_running ++ ++ if pk_auth_running: ++ # FIXME: raise an exception: this should really never happen ++ return False ++ ++ pk_auth_ret = False ++ pk_auth_error = None ++ pk_auth_done = False ++ + pk_auth_object = self._session_bus.get_object(PK_AUTH_NAME, PK_AUTH_PATH) + pk_auth = dbus.Interface(pk_auth_object, PK_AUTH_IFACE) + -+ ret = pk_auth.ObtainAuthorization(action, dbus.UInt32(xid), dbus.UInt32(os.getpid())) ++ # We're doing this dbus call asynchronously because we want to not ++ # freeze the UI while a menu is being destroyed. And the windows might ++ # need some repainting while the authorization dialog is displayed. ++ pk_auth_running = True ++ ++ pk_auth.ObtainAuthorization(action, dbus.UInt32(xid), dbus.UInt32(os.getpid()), reply_handler=_pk_auth_reply_handler, error_handler=_pk_auth_error_handler) ++ ++ while not pk_auth_done: ++ gtk.main_iteration(True) + -+ if not type(ret) == dbus.Boolean: ++ pk_auth_running = False ++ ++ if pk_auth_error != None: ++ raise dbus.exceptions.DBusException(pk_auth_error) ++ ++ if not type(pk_auth_ret) == dbus.Boolean: + return False + -+ return ret != 0 ++ return pk_auth_ret != 0 + + + def _handle_exception_with_auth(self, e, fallback, *args, **kwds): @@ -135,21 +225,50 @@ index 0000000..b5d9e7f + return False + + try: -+ # FIXME use self._parent from authconn.py -+ ret = self._obtain_auth(tokens[0], 0) -+ except dbus.exceptions.DBusException, e_auth: ++ xid = 0 ++ if self._parent and getattr(self._parent, 'window') and getattr(self._parent.window, 'xid'): ++ xid = self._parent.window.xid ++ ++ # FIXME: is xid working? ++ ret = self._obtain_auth(tokens[0], xid) ++ except dbus.exceptions.DBusException: + fallback(*args, **kwds) + return False + + if not ret: -+ raise cups.IPPError(cups.IPP_NOT_AUTHORIZED, '') ++ raise cups.IPPError(cups.IPP_NOT_AUTHORIZED, 'pkcancel') + + return True + + ++ def _call_with_pk_and_fallback(self, use_fallback, pk_function_name, pk_args, fallback_function, *args, **kwds): ++ pk_function = None ++ ++ if not use_fallback: ++ cups_pk = self._get_cups_pk() ++ if cups_pk: ++ try: ++ pk_function = cups_pk.get_dbus_method(pk_function_name) ++ except dbus.exceptions.DBusException: ++ pass ++ ++ if use_fallback or not pk_function: ++ fallback_function(*args, **kwds) ++ return ++ ++ while True: ++ try: ++ # FIXME: async call or not? ++ pk_function(*pk_args) ++ break ++ except dbus.exceptions.DBusException, e: ++ if not self._handle_exception_with_auth(e, fallback_function, *args, **kwds): ++ break ++ ++ + def _args_to_tuple(self, types, *args): + if len(types) != len(args): -+ types.append(False) ++ types.append(True) + return types + + exception = False @@ -161,6 +280,10 @@ index 0000000..b5d9e7f + if types[i] == str and type(args[i]) == unicode: + # we accept a mix between unicode and str + pass ++ elif types[i] == str and args[i] == None: ++ # None is an empty string for dbus ++ retval.append('') ++ continue + else: + exception = True + retval.append(args[i]) @@ -177,34 +300,11 @@ index 0000000..b5d9e7f + if kwds.has_key(name): + ret.append(kwds[name]) + else: -+ ret.append(None) ++ ret.append('') + + return tuple(ret) + + -+ def _call_with_pk_and_fallback(self, use_fallback, pk_function_name, pk_args, fallback_function, *args, **kwds): -+ pk_function = None -+ -+ if not use_fallback: -+ cups_pk = self._get_cups_pk() -+ if cups_pk: -+ try: -+ pk_function = cups_pk.get_dbus_method(pk_function_name) -+ except dbus.exceptions.DBusException: -+ pass -+ -+ if use_fallback or not pk_function: -+ fallback_function(*args, **kwds) -+ return -+ -+ while True: -+ try: -+ pk_function(*pk_args) -+ break -+ except dbus.exceptions.DBusException, e: -+ if not self._handle_exception_with_auth(e, fallback_function, *args, **kwds): -+ break -+ +# getPrinters +# getDests +# getClasses @@ -400,7 +500,8 @@ index 0000000..b5d9e7f + + + def rejectJobs(self, *args, **kwds): -+ (name, reason, use_pycups) = self._args_to_tuple([str, str], *args) ++ (name, use_pycups) = self._args_to_tuple([str], *args) ++ (reason,) = self._kwds_to_vars(['reason'], **kwds) + pk_args = (name, False, reason) + + self._call_with_pk_and_fallback(use_pycups, diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/po/ChangeLog diff --git a/po/POTFILES.in b/po/POTFILES.in index 53c4283..8e9383d 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,3 +1,4 @@ # List of source files containing translatable strings. # Please keep this file sorted alphabetically. [encoding: UTF-8] +src/org.opensuse.cupspkhelper.mechanism.policy.in diff --git a/src/test-cups-pk.c b/src/test-cups-pk.c index ec86a30..d797d04 100644 --- a/src/test-cups-pk.c +++ b/src/test-cups-pk.c @@ -159,7 +159,9 @@ main (int argc, char **argv) tokens = g_strsplit (error->message, " ", 2); g_error_free (error); if (g_strv_length (tokens) == 2) { - /* FIXME: this fails because of timeout if the user waits too long */ + /* Note: the async version fails + * because of timeout if the user waits + * too long */ try = do_auth (session_bus, tokens[0], tokens[1]); if (!try) g_print ("not authorized\n"); diff --git a/src/test-cups-pk.py b/src/test-cups-pk.py index aba3aca..30cd231 100755 --- a/src/test-cups-pk.py +++ b/src/test-cups-pk.py @@ -47,6 +47,8 @@ def handle_exception_with_auth(session_bus, e): return False try: + # Note: the async version fails because of timeout if the user waits + # too long ret = pk_auth(session_bus, tokens[0], tokens[1]) except dbus.exceptions.DBusException, e_auth: print 'dbus error: %s' % e_auth |