diff options
author | Vincent Untz <vuntz@novell.com> | 2008-09-22 03:10:13 +0200 |
---|---|---|
committer | Vincent Untz <vuntz@novell.com> | 2008-09-22 03:10:13 +0200 |
commit | 30b23465704727a89cfcc2d0e8c9e2225d220d77 (patch) | |
tree | 54157866b5a202d7972570f009e9cc634945e2ea | |
parent | e992a74d8f8ef2b0e28c035322ab67b97afd3f0f (diff) |
Add quite some stuff, and the current patch to s-c-p.
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | patches/system-config-printer.patch | 421 | ||||
-rw-r--r-- | src/cups-pk-helper-mechanism.c | 329 | ||||
-rw-r--r-- | src/cups-pk-helper-mechanism.h | 105 | ||||
-rw-r--r-- | src/cups-pk-helper-mechanism.xml | 102 | ||||
-rw-r--r-- | src/cups.c | 99 | ||||
-rw-r--r-- | src/cups.h | 7 | ||||
-rw-r--r-- | src/org.opensuse.cupspkhelper.mechanism.policy.in | 6 | ||||
-rwxr-xr-x | src/test-cups-pk.py | 106 | ||||
-rw-r--r-- | src/test-cups.c | 2 |
10 files changed, 1127 insertions, 52 deletions
diff --git a/configure.ac b/configure.ac index 560a034..5ef3f63 100644 --- a/configure.ac +++ b/configure.ac @@ -44,7 +44,6 @@ DBUS_REQUIRED=1.1.2 DBUS_GLIB_REQUIRED=0.74 POLKIT_DBUS_REQUIRED=0.8 GTK_REQUIRED=2.12.0 -POLKIT_GNOME_REQUIRED=0.7 # pkg-config dependency checks PKG_CHECK_MODULES(CUPS_PK, glib-2.0 >= $GLIB_REQUIRED \ @@ -58,7 +57,6 @@ AC_SUBST(CUPS_PK_CFLAGS) AC_SUBST(CUPS_PK_LIBS) PKG_CHECK_MODULES(CUPS_PK_GNOME, gtk+-2.0 >= $GTK_REQUIRED \ - polkit-gnome >= $POLKIT_GNOME_REQUIRED \ dbus-1 >= $DBUS_REQUIRED \ dbus-glib-1 >= $DBUS_GLIB_REQUIRED) AC_SUBST(CUPS_PK_GNOME_CFLAGS) diff --git a/patches/system-config-printer.patch b/patches/system-config-printer.patch new file mode 100644 index 0000000..7e26f38 --- /dev/null +++ b/patches/system-config-printer.patch @@ -0,0 +1,421 @@ +diff --git a/authconn.py b/authconn.py +index 6244eee..4fff0d1 100644 +--- a/authconn.py ++++ b/authconn.py +@@ -18,6 +18,7 @@ + ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + import cups ++import cupspk + import gtk + from debug import * + +@@ -120,8 +121,15 @@ class Connection: + + def _connect (self): + cups.setUser (self._use_user) ++ ++ self._use_pk = self._server[0] == '/' or self._server == 'localhost' ++ if self._use_pk: ++ create_object = cupspk.Connection ++ else: ++ create_object = cups.Connection ++ + try: +- self._connection = cups.Connection (host=self._server, ++ self._connection = create_object (host=self._server, + port=self._port, + encryption=self._encryption) + except TypeError: +@@ -129,16 +137,17 @@ class Connection: + cups.setServer (self._server) + cups.setPort (self._port) + cups.setEncryption (self._encryption) +- self._connection = cups.Connection () ++ self._connection = create_object () + + self._user = self._use_user + debugprint ("Connected as user %s" % self._user) +- methodtype = type (self._connection.getPrinters) ++ methodtype_lambda = type (self._connection.getPrinters) ++ methodtype_real = type (self._connection.addPrinter) + for fname in dir (self._connection): + if fname[0] == '_': + continue + fn = getattr (self._connection, fname) +- if type (fn) != methodtype: ++ if not type (fn) in [methodtype_lambda, methodtype_real]: + continue + setattr (self, fname, self._make_binding (fname, fn)) + +diff --git a/cupspk.py b/cupspk.py +new file mode 100644 +index 0000000..b5d9e7f +--- /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 ++# check FIXME/TODO in cups-pk-helper ++# define fine-grained policy (more than one level of permission) ++ ++import os ++ ++import tempfile ++ ++import cups ++import dbus ++ ++PK_AUTH_NAME = 'org.freedesktop.PolicyKit.AuthenticationAgent' ++PK_AUTH_PATH = '/' ++PK_AUTH_IFACE = 'org.freedesktop.PolicyKit.AuthenticationAgent' ++ ++CUPS_PK_NAME = 'org.opensuse.CupsPkHelper.Mechanism' ++CUPS_PK_PATH = '/' ++CUPS_PK_IFACE = 'org.opensuse.CupsPkHelper.Mechanism' ++ ++CUPS_PK_NEED_AUTH = 'org.opensuse.CupsPkHelper.Mechanism.NotPrivileged' ++ ++# 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._session_bus = dbus.SessionBus() ++ self._system_bus = dbus.SystemBus() ++ ++ self._connection = cups.Connection(host=host, ++ port=port, ++ encryption=encryption) ++ ++ self._hack_subclass() ++ ++ ++ def _hack_subclass(self): ++ # here's how to subclass without really subclassing. Just provide ++ # the same methods ++ methodtype = type(self._connection.getPrinters) ++ for fname in dir(self._connection): ++ if fname[0] == '_': ++ continue ++ fn = getattr(self._connection, fname) ++ if type(fn) != methodtype: ++ continue ++ if not hasattr(self, fname): ++ setattr(self, fname, fn.__call__) ++ ++ ++ def _get_cups_pk(self): ++ try: ++ object = self._system_bus.get_object(CUPS_PK_NAME, CUPS_PK_PATH) ++ return dbus.Interface(object, CUPS_PK_IFACE) ++ except dbus.exceptions.DBusException: ++ return None ++ ++ ++ def _obtain_auth(self, action, xid = 0): ++ 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())) ++ ++ if not type(ret) == dbus.Boolean: ++ return False ++ ++ return ret != 0 ++ ++ ++ def _handle_exception_with_auth(self, e, fallback, *args, **kwds): ++ if e.get_dbus_name() != CUPS_PK_NEED_AUTH: ++ fallback(*args, **kwds) ++ return False ++ ++ tokens = e.get_dbus_message().split(' ', 2) ++ if len(tokens) != 3: ++ fallback(*args, **kwds) ++ return False ++ ++ try: ++ # FIXME use self._parent from authconn.py ++ ret = self._obtain_auth(tokens[0], 0) ++ except dbus.exceptions.DBusException, e_auth: ++ fallback(*args, **kwds) ++ return False ++ ++ if not ret: ++ raise cups.IPPError(cups.IPP_NOT_AUTHORIZED, '') ++ ++ return True ++ ++ ++ def _args_to_tuple(self, types, *args): ++ if len(types) != len(args): ++ types.append(False) ++ return types ++ ++ exception = False ++ ++ retval = [] ++ ++ for i in range(len(types)): ++ if type(args[i]) != types[i]: ++ if types[i] == str and type(args[i]) == unicode: ++ # we accept a mix between unicode and str ++ pass ++ else: ++ exception = True ++ retval.append(args[i]) ++ ++ retval.append(exception) ++ ++ return tuple(retval) ++ ++ ++ def _kwds_to_vars(self, names, **kwds): ++ ret = [] ++ ++ for name in names: ++ if kwds.has_key(name): ++ ret.append(kwds[name]) ++ else: ++ ret.append(None) ++ ++ 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 ++# getPPDs ++# getServerPPD ++# getDocument ++# getDevices ++# getJobs ++# getJobAttributes ++# cancelJob ++# cancelAllJobs ++# authenticateJob ++# setJobHoldUntil ++# restartJob ++# getFile ++# putFile ++ ++ def addPrinter(self, *args, **kwds): ++ (name, use_pycups) = self._args_to_tuple([str], *args) ++ (filename, ppdname, info, location, device, ppd) = self._kwds_to_vars(['filename', 'ppdname', 'info', 'location', 'device', 'ppd'], **kwds) ++ ++ need_unlink = False ++ if not ppdname and not filename and ppd: ++ (fd, filename) = tempfile.mkstemp () ++ ppd.writeFd(fd) ++ os.close(fd) ++ need_unlink = True ++ ++ if filename and not ppdname: ++ pk_args = (name, device, filename, info, location) ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterAddWithPpdFile', pk_args, ++ self._connection.addPrinter, ++ *args, **kwds) ++ if need_unlink: ++ os.unlink(filename) ++ else: ++ pk_args = (name, device, ppdname, info, location) ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterAdd', pk_args, ++ self._connection.addPrinter, ++ *args, **kwds) ++ ++ ++ def setPrinterDevice(self, *args, **kwds): ++ (name, device, use_pycups) = self._args_to_tuple([str, str], *args) ++ pk_args = (name, device) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetDevice', pk_args, ++ self._connection.setPrinterDevice, ++ *args, **kwds) ++ ++ ++ def setPrinterInfo(self, *args, **kwds): ++ (name, info, use_pycups) = self._args_to_tuple([str, str], *args) ++ pk_args = (name, info) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetInfo', pk_args, ++ self._connection.setPrinterInfo, ++ *args, **kwds) ++ ++ ++ def setPrinterLocation(self, *args, **kwds): ++ (name, location, use_pycups) = self._args_to_tuple([str, str], *args) ++ pk_args = (name, location) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetLocation', pk_args, ++ self._connection.setPrinterLocation, ++ *args, **kwds) ++ ++ ++ def setPrinterShared(self, *args, **kwds): ++ (name, shared, use_pycups) = self._args_to_tuple([str, bool], *args) ++ pk_args = (name, shared) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetShared', pk_args, ++ self._connection.setPrinterShared, ++ *args, **kwds) ++ ++ ++ def setPrinterJobSheets(self, *args, **kwds): ++ (name, start, end, use_pycups) = self._args_to_tuple([str, str, str], *args) ++ pk_args = (name, start, end) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetJobSheets', pk_args, ++ self._connection.setPrinterJobSheets, ++ *args, **kwds) ++ ++ ++ def setPrinterErrorPolicy(self, *args, **kwds): ++ (name, policy, use_pycups) = self._args_to_tuple([str, str], *args) ++ pk_args = (name, policy) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetErrorPolicy', pk_args, ++ self._connection.setPrinterErrorPolicy, ++ *args, **kwds) ++ ++ ++ def setPrinterOpPolicy(self, *args, **kwds): ++ (name, policy, use_pycups) = self._args_to_tuple([str, str], *args) ++ pk_args = (name, policy) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetOpPolicy', pk_args, ++ self._connection.setPrinterOpPolicy, ++ *args, **kwds) ++ ++ ++# setPrinterUsersAllowed ++# setPrinterUsersDenied ++ ++ def addPrinterOptionDefault(self, *args, **kwds): ++ #FIXME: value can be a sequence (need to fix dbus API too) ++ (name, option, value, use_pycups) = self._args_to_tuple([str, str, str], *args) ++ pk_args = (name, option, value) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterAddOptionDefault', pk_args, ++ self._connection.addPrinterOptionDefault, ++ *args, **kwds) ++ ++ ++ def deletePrinterOptionDefault(self, *args, **kwds): ++ (name, option, use_pycups) = self._args_to_tuple([str, str], *args) ++ pk_args = (name, option) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterDeleteOptionDefault', pk_args, ++ self._connection.deletePrinterOptionDefault, ++ *args, **kwds) ++ ++ ++ def deletePrinter(self, *args, **kwds): ++ (name, use_pycups) = self._args_to_tuple([str], *args) ++ pk_args = (name,) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterDelete', pk_args, ++ self._connection.deletePrinter, ++ *args, **kwds) ++ ++# getPrinterAttributes ++# addPrinterToClass ++# deletePrinterFromClass ++# deleteClass ++# getDefault ++ ++ def setDefault(self, *args, **kwds): ++ (name, use_pycups) = self._args_to_tuple([str], *args) ++ pk_args = (name,) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetDefault', pk_args, ++ self._connection.setDefault, ++ *args, **kwds) ++ ++# getPPD ++ ++ def enablePrinter(self, *args, **kwds): ++ (name, use_pycups) = self._args_to_tuple([str], *args) ++ pk_args = (name, True) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetEnabled', pk_args, ++ self._connection.enablePrinter, ++ *args, **kwds) ++ ++ ++ def disablePrinter(self, *args, **kwds): ++ (name, use_pycups) = self._args_to_tuple([str], *args) ++ pk_args = (name, False) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetEnabled', pk_args, ++ self._connection.enablePrinter, ++ *args, **kwds) ++ ++ ++ def acceptJobs(self, *args, **kwds): ++ (name, use_pycups) = self._args_to_tuple([str], *args) ++ pk_args = (name, True, '') ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetAcceptJobs', pk_args, ++ self._connection.acceptJobs, ++ *args, **kwds) ++ ++ ++ def rejectJobs(self, *args, **kwds): ++ (name, reason, use_pycups) = self._args_to_tuple([str, str], *args) ++ pk_args = (name, False, reason) ++ ++ self._call_with_pk_and_fallback(use_pycups, ++ 'PrinterSetAcceptJobs', pk_args, ++ self._connection.rejectJobs, ++ *args, **kwds) ++ ++ ++# printTestPage ++# adminGetServerSettings ++# adminSetServerSettings ++# getSubscriptions ++# createSubscription ++# getNotifications ++# cancelSubscription ++# renewSubscription ++# printFile ++# printFiles diff --git a/src/cups-pk-helper-mechanism.c b/src/cups-pk-helper-mechanism.c index 91944e3..45c5fd9 100644 --- a/src/cups-pk-helper-mechanism.c +++ b/src/cups-pk-helper-mechanism.c @@ -358,30 +358,329 @@ _check_polkit_for_action (CphMechanism *mechanism, return TRUE; } +/* helpers */ + +static void +_cph_mechanism_return_error (CphMechanism *mechanism, + DBusGMethodInvocation *context, + gboolean failed) +{ + const char *error; + + if (failed) + error = cph_cups_last_status_to_string (mechanism->priv->cups); + else + error = ""; + + dbus_g_method_return (context, error); +} + /* exported methods */ gboolean -cph_mechanism_printer_add (CphMechanism *mechanism, - const char *name, - const char *uri, - const char *ppd, - const char *info, - const char *location, - DBusGMethodInvocation *context) +cph_mechanism_printer_add (CphMechanism *mechanism, + const char *name, + const char *uri, + const char *ppd, + const char *info, + const char *location, + DBusGMethodInvocation *context) { - const char *error; + gboolean ret; reset_killtimer (mechanism); - if (!_check_polkit_for_action (mechanism, context, "printeradd")) + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) return FALSE; - if (!cph_cups_printer_add (mechanism->priv->cups, - name, uri, ppd, info, location)) - error = cph_cups_last_status_to_string (mechanism->priv->cups); - else - error = ""; + ret = cph_cups_printer_add (mechanism->priv->cups, + name, uri, ppd, info, location); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_add_with_ppd_file (CphMechanism *mechanism, + const char *name, + const char *uri, + const char *ppdfile, + const char *info, + const char *location, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_add_with_ppd_file (mechanism->priv->cups, + name, uri, ppdfile, + info, location); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_device (CphMechanism *mechanism, + const char *name, + const char *device, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_set_uri (mechanism->priv->cups, + name, device); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_info (CphMechanism *mechanism, + const char *name, + const char *info, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_info (mechanism->priv->cups, + name, info); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_location (CphMechanism *mechanism, + const char *name, + const char *location, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_location (mechanism->priv->cups, + name, location); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_shared (CphMechanism *mechanism, + const char *name, + gboolean shared, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_shared (mechanism->priv->cups, + name, shared); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_job_sheets (CphMechanism *mechanism, + const char *name, + const char *start, + const char *end, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_job_sheets (mechanism->priv->cups, + name, start, end); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_error_policy (CphMechanism *mechanism, + const char *name, + const char *policy, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_error_policy (mechanism->priv->cups, + name, policy); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_op_policy (CphMechanism *mechanism, + const char *name, + const char *policy, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_op_policy (mechanism->priv->cups, + name, policy); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_add_option_default (CphMechanism *mechanism, + const char *name, + const char *option, + const char *value, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_option_default (mechanism->priv->cups, + name, option, value, + NULL); + _cph_mechanism_return_error (mechanism, context, !ret); + + + return TRUE; +} + +gboolean +cph_mechanism_printer_delete_option_default (CphMechanism *mechanism, + const char *name, + const char *option, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_class_set_option_default (mechanism->priv->cups, + name, option, NULL); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_delete (CphMechanism *mechanism, + const char *name, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_delete (mechanism->priv->cups, name); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_default (CphMechanism *mechanism, + const char *name, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_set_default (mechanism->priv->cups, name); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_enabled (CphMechanism *mechanism, + const char *name, + gboolean enabled, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_set_enabled (mechanism->priv->cups, + name, enabled); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_printer_set_accept_jobs (CphMechanism *mechanism, + const char *name, + gboolean enabled, + const char *reason, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_printer_set_accept_jobs (mechanism->priv->cups, + name, enabled, reason); + _cph_mechanism_return_error (mechanism, context, !ret); - dbus_g_method_return (context, error); return TRUE; } diff --git a/src/cups-pk-helper-mechanism.h b/src/cups-pk-helper-mechanism.h index c005ad2..cc86e7d 100644 --- a/src/cups-pk-helper-mechanism.h +++ b/src/cups-pk-helper-mechanism.h @@ -74,14 +74,103 @@ CphMechanism *cph_mechanism_new (void); /* exported methods */ -gboolean cph_mechanism_printer_add (CphMechanism *mechanism, - const char *name, - const char *uri, - const char *ppd, - const char *info, - const char *location, - DBusGMethodInvocation *context); - +gboolean +cph_mechanism_printer_add (CphMechanism *mechanism, + const char *name, + const char *uri, + const char *ppd, + const char *info, + const char *location, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_add_with_ppd_file (CphMechanism *mechanism, + const char *name, + const char *uri, + const char *ppdfile, + const char *info, + const char *location, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_device (CphMechanism *mechanism, + const char *name, + const char *device, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_info (CphMechanism *mechanism, + const char *name, + const char *info, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_location (CphMechanism *mechanism, + const char *name, + const char *location, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_shared (CphMechanism *mechanism, + const char *name, + gboolean shared, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_job_sheets (CphMechanism *mechanism, + const char *name, + const char *start, + const char *end, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_error_policy (CphMechanism *mechanism, + const char *name, + const char *policy, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_op_policy (CphMechanism *mechanism, + const char *name, + const char *policy, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_add_option_default (CphMechanism *mechanism, + const char *name, + const char *option, + const char *value, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_delete_option_default (CphMechanism *mechanism, + const char *name, + const char *option, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_delete (CphMechanism *mechanism, + const char *name, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_default (CphMechanism *mechanism, + const char *name, + DBusGMethodInvocation *context); + +gboolean +cph_mechanism_printer_set_enabled (CphMechanism *mechanism, + const char *name, + gboolean enabled, + DBusGMethodInvocation *context); + + +gboolean +cph_mechanism_printer_set_accept_jobs (CphMechanism *mechanism, + const char *name, + gboolean enabled, + const char *reason, + DBusGMethodInvocation *context); G_END_DECLS #endif /* CPH_MECHANISM_H */ diff --git a/src/cups-pk-helper-mechanism.xml b/src/cups-pk-helper-mechanism.xml index 74eb4a5..ddce8cd 100644 --- a/src/cups-pk-helper-mechanism.xml +++ b/src/cups-pk-helper-mechanism.xml @@ -10,5 +10,107 @@ <arg name="location" direction="in" type="s"/> <arg name="error" direction="out" type="s"/> </method> + + <method name="PrinterAddWithPpdFile"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="uri" direction="in" type="s"/> + <arg name="ppd" direction="in" type="s"/> + <arg name="info" direction="in" type="s"/> + <arg name="location" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetDevice"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="device" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetInfo"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="info" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetLocation"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="location" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetShared"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="shared" direction="in" type="b"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetJobSheets"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="start" direction="in" type="s"/> + <arg name="end" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetErrorPolicy"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="policy" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetOpPolicy"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="policy" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterAddOptionDefault"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="option" direction="in" type="s"/> + <arg name="value" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterDeleteOptionDefault"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="option" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterDelete"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetDefault"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetEnabled"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="enabled" direction="in" type="b"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="PrinterSetAcceptJobs"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="enabled" direction="in" type="b"/> + <arg name="reason" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> </interface> </node> @@ -61,30 +61,30 @@ ! restartJob getFile putFile -~! addPrinter -~! setPrinterDevice -~! setPrinterInfo -~! setPrinterLocation -~! setPrinterShared -~! setPrinterJobSheets -~! setPrinterErrorPolicy -~! setPrinterOpPolicy +~!+* addPrinter +~!+* setPrinterDevice +~!+* setPrinterInfo +~!+* setPrinterLocation +~!+* setPrinterShared +~!+* setPrinterJobSheets +~!+* setPrinterErrorPolicy +~!+* setPrinterOpPolicy ! setPrinterUsersAllowed ! setPrinterUsersDenied -~! addPrinterOptionDefault -~! deletePrinterOptionDefault -~! deletePrinter +~!+* addPrinterOptionDefault +~!+* deletePrinterOptionDefault +~!+* deletePrinter getPrinterAttributes ! addPrinterToClass ! deletePrinterFromClass ! deleteClass getDefault -~! setDefault +~!+* setDefault getPPD -~! enablePrinter -~! disablePrinter -~! acceptJobs -~! rejectJobs +~!+* enablePrinter +~!+* disablePrinter +~!+* acceptJobs +~!+* rejectJobs printTestPage ! adminGetServerSettings ! adminSetServerSettings @@ -237,13 +237,10 @@ _cph_cups_set_error_from_reply (CphCups *cups, } static gboolean -_cph_cups_send_request (CphCups *cups, - ipp_t *request) +_cph_cups_handle_reply (CphCups *cups, + ipp_t *reply) { gboolean retval; - ipp_t *reply; - - reply = cupsDoRequest (cups->priv->connection, request, "/"); if (!reply || reply->request.status.status_code > IPP_OK_CONFLICT) { retval = FALSE; @@ -260,6 +257,29 @@ _cph_cups_send_request (CphCups *cups, } static gboolean +_cph_cups_send_request (CphCups *cups, + ipp_t *request) +{ + ipp_t *reply; + + reply = cupsDoRequest (cups->priv->connection, request, "/"); + + return _cph_cups_handle_reply (cups, reply); +} + +static gboolean +_cph_cups_post_request (CphCups *cups, + ipp_t *request, + const char *file) +{ + ipp_t *reply; + + reply = cupsDoFileRequest (cups->priv->connection, request, "/", file); + + return _cph_cups_handle_reply (cups, reply); +} + +static gboolean _cph_cups_send_new_simple_request (CphCups *cups, ipp_op_t op, const char *printer_name) @@ -270,7 +290,7 @@ _cph_cups_send_new_simple_request (CphCups *cups, /* FIXME: set status */ return FALSE; - request = ippNewRequest (IPP_PAUSE_PRINTER); + request = ippNewRequest (op); _cph_cups_add_printer_uri (request, printer_name); return _cph_cups_send_request (cups, request); @@ -324,7 +344,6 @@ cph_cups_printer_add (CphCups *cups, const char *info, const char *location) { - /* TODO: we might need to support putting a file on the server */ ipp_t *request; g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); @@ -354,6 +373,40 @@ cph_cups_printer_add (CphCups *cups, } gboolean +cph_cups_printer_add_with_ppd_file (CphCups *cups, + const char *printer_name, + const char *printer_uri, + const char *ppd_filename, + const char *info, + const char *location) +{ + ipp_t *request; + + g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); + + /* FIXME check arguments are fine */ + + request = ippNewRequest (CUPS_ADD_MODIFY_PRINTER); + _cph_cups_add_printer_uri (request, printer_name); + + ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_NAME, + "printer-name", NULL, printer_name); + ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_URI, + "device-uri", NULL, printer_uri); + + if (info) { + ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_TEXT, + "printer-info", NULL, info); + } + if (location) { + ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_TEXT, + "printer-location", NULL, location); + } + + return _cph_cups_post_request (cups, request, ppd_filename); +} + +gboolean cph_cups_printer_delete (CphCups *cups, const char *printer_name) { @@ -61,6 +61,13 @@ gboolean cph_cups_printer_add (CphCups *cups, const char *info, const char *location); +gboolean cph_cups_printer_add_with_ppd_file (CphCups *cups, + const char *printer_name, + const char *printer_uri, + const char *ppd_filename, + const char *info, + const char *location); + gboolean cph_cups_printer_delete (CphCups *cups, const char *printer_name); diff --git a/src/org.opensuse.cupspkhelper.mechanism.policy.in b/src/org.opensuse.cupspkhelper.mechanism.policy.in index 892309d..a316e15 100644 --- a/src/org.opensuse.cupspkhelper.mechanism.policy.in +++ b/src/org.opensuse.cupspkhelper.mechanism.policy.in @@ -8,9 +8,9 @@ <vendor_url>http://www.opensuse.org/</vendor_url> <icon_name>printer</icon_name> - <action id="org.opensuse.cupspkhelper.mechanism.printeradd"> - <_description>Add a printer</_description> - <_message>Privileges are required to add a printer.</_message> + <action id="org.opensuse.cupspkhelper.mechanism.printeraddremove"> + <_description>Add/Remove a printer</_description> + <_message>Privileges are required to add/remove a printer.</_message> <defaults> <allow_inactive>no</allow_inactive> <allow_active>auth_admin</allow_active> diff --git a/src/test-cups-pk.py b/src/test-cups-pk.py new file mode 100755 index 0000000..aba3aca --- /dev/null +++ b/src/test-cups-pk.py @@ -0,0 +1,106 @@ +#!/usr/bin/python +# 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. +# + +import os +import sys + +import dbus + +def pk_auth(bus, action, result): + pk_auth_object =bus.get_object('org.freedesktop.PolicyKit.AuthenticationAgent', '/') + pk_auth = dbus.Interface(pk_auth_object, 'org.freedesktop.PolicyKit.AuthenticationAgent') + + ret = pk_auth.ObtainAuthorization(action, dbus.UInt32(0), dbus.UInt32(os.getpid())) + + if not type(ret) == dbus.Boolean: + return False + + return ret != 0 + +def handle_exception_with_auth(session_bus, e): + if e.get_dbus_name() != 'org.opensuse.CupsPkHelper.Mechanism.NotPrivileged': + print 'dbus error: %s' % e + return False + + tokens = e.get_dbus_message().split(' ', 2) + if len(tokens) != 3: + print 'helper return string malformed' + return False + + try: + ret = pk_auth(session_bus, tokens[0], tokens[1]) + except dbus.exceptions.DBusException, e_auth: + print 'dbus error: %s' % e_auth + return False + + if not ret: + print 'not authorized' + + return ret + +def removeprinter(cups_pk, printer_name): + error = cups_pk.PrinterRemove(printer_name) + + if not type(error) in [dbus.String, dbus.UTF8String]: + print 'unexpected return value' + return + + if error == '': + print 'worked!' + else: + print 'ouch: %s' % error + +def addprinter(cups_pk, printer_name, printer_uri, ppd_file, info, location): + error = cups_pk.PrinterAdd(printer_name, printer_uri, ppd_file, info, location) + + if not type(error) in [dbus.String, dbus.UTF8String]: + print 'unexpected return value' + return + + if error == '': + print 'worked!' + else: + print 'ouch: %s' % error + +def main(args): + session_bus = dbus.SessionBus() + system_bus = dbus.SystemBus() + + cups_pk_object = system_bus.get_object('org.opensuse.CupsPkHelper.Mechanism', '/') + cups_pk_interface = dbus.Interface(cups_pk_object, 'org.opensuse.CupsPkHelper.Mechanism') + + while True: + try: + #removeprinter(cups_pk_interface, "MyPrinter") + addprinter(cups_pk_interface, "MyPrinter", "smb://really/cool", "HP/Business_Inkjet_2200-chp2200.ppd.gz", "This is my printer", "At home") + break + except dbus.exceptions.DBusException, e: + if handle_exception_with_auth(session_bus, e): + continue + break + + +if __name__ == '__main__': + try: + main(sys.argv) + except KeyboardInterrupt: + pass diff --git a/src/test-cups.c b/src/test-cups.c index e22612a..cf68467 100644 --- a/src/test-cups.c +++ b/src/test-cups.c @@ -39,7 +39,7 @@ main (int argc, char **argv) return 1; //if (cph_cups_add_printer (cups, "MyPrinter", "smb://really/cool", "HP/Business_Inkjet_2200-chp2200.ppd.gz", "This is my printer", "At home")) { - //if (cph_cups_delete_printer (cups, "MyPrinter")) { + //if (cph_cups_printer_delete (cups, "MyPrinter")) { if (cph_cups_printer_class_set_job_sheets (cups, "DesignJet-650C", "none", "none")) { g_print ("worked\n"); } else { |