summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Untz <vuntz@novell.com>2008-09-22 03:10:13 +0200
committerVincent Untz <vuntz@novell.com>2008-09-22 03:10:13 +0200
commit30b23465704727a89cfcc2d0e8c9e2225d220d77 (patch)
tree54157866b5a202d7972570f009e9cc634945e2ea
parente992a74d8f8ef2b0e28c035322ab67b97afd3f0f (diff)
Add quite some stuff, and the current patch to s-c-p.
-rw-r--r--configure.ac2
-rw-r--r--patches/system-config-printer.patch421
-rw-r--r--src/cups-pk-helper-mechanism.c329
-rw-r--r--src/cups-pk-helper-mechanism.h105
-rw-r--r--src/cups-pk-helper-mechanism.xml102
-rw-r--r--src/cups.c99
-rw-r--r--src/cups.h7
-rw-r--r--src/org.opensuse.cupspkhelper.mechanism.policy.in6
-rwxr-xr-xsrc/test-cups-pk.py106
-rw-r--r--src/test-cups.c2
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>
diff --git a/src/cups.c b/src/cups.c
index 018c93e..f8b2b9e 100644
--- a/src/cups.c
+++ b/src/cups.c
@@ -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)
{
diff --git a/src/cups.h b/src/cups.h
index f647ca8..8f931b6 100644
--- a/src/cups.h
+++ b/src/cups.h
@@ -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 {