summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Untz <vuntz@novell.com>2008-09-21 06:48:34 +0200
committerVincent Untz <vuntz@novell.com>2008-09-21 06:48:34 +0200
commite992a74d8f8ef2b0e28c035322ab67b97afd3f0f (patch)
treef672a40e07c9016a46e282494f4c62d8c0a535bd
parentb4276a418cda637167be754a9dd5574505485fdf (diff)
First pass at this.
There are two smalls test program to show this works :-)
-rw-r--r--.gitignore8
-rwxr-xr-xautogen.sh2
-rw-r--r--configure.ac16
-rw-r--r--src/Makefile.am41
-rw-r--r--src/cups-methods.c0
-rw-r--r--src/cups-pk-helper-mechanism.c101
-rw-r--r--src/cups-pk-helper-mechanism.h9
-rw-r--r--src/cups-pk-helper-mechanism.xml11
-rw-r--r--src/cups.c683
-rw-r--r--src/cups.h115
-rw-r--r--src/main.c4
-rw-r--r--src/org.opensuse.CupsPkHelper.Mechanism.conf (renamed from src/org.opensuse.cups-pk-helper.Mechanism.conf)4
-rw-r--r--src/org.opensuse.CupsPkHelper.Mechanism.service.in (renamed from src/org.opensuse.cups-pk-helper.Mechanism.service.in)2
-rw-r--r--src/org.opensuse.cupspkhelper.mechanism.policy.in (renamed from src/org.opensuse.cups-pk-helper.mechanism.policy.in)9
-rw-r--r--src/test-cups-pk.c178
-rw-r--r--src/test-cups.c52
16 files changed, 1212 insertions, 23 deletions
diff --git a/.gitignore b/.gitignore
index c12d96e..881056e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,7 @@ autom4te.cache/
compile
config.guess
config.h
-config.h.in
+config.h.in*
config.log
config.status
config.sub
@@ -33,6 +33,8 @@ src/Makefile
src/Makefile.in
src/cups-pk-helper-mechanism
src/cups-pk-helper-mechanism-glue.h
-src/org.opensuse.cups-pk-helper.Mechanism.service
-src/org.opensuse.cups-pk-helper.mechanism.policy
+src/org.opensuse.CupsPkHelper.Mechanism.service
+src/org.opensuse.cupspkhelper.mechanism.policy
+src/test-cups
+src/test-cups-pk
stamp-h1
diff --git a/autogen.sh b/autogen.sh
index 63738e4..313bcf5 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -7,7 +7,7 @@ test -z "$srcdir" && srcdir=.
PKG_NAME="CUPS PolicyKit helper"
(test -f $srcdir/configure.ac \
- && test -f $srcdir/src/cups-methods.c) || {
+ && test -f $srcdir/src/cups-pk-helper-mechanism.c) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level package directory"
exit 1
diff --git a/configure.ac b/configure.ac
index 4b42b54..560a034 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_INIT([cups-pk-helper], [0.0.1],
[https://bugzilla.novell.com/enter_bug.cgi?classification=7340&product=openSUSE+11.1])
-AC_CONFIG_SRCDIR(src/cups-methods.c)
+AC_CONFIG_SRCDIR(src/cups-pk-helper-mechanism.c)
AM_INIT_AUTOMAKE([1.9 no-dist-gzip dist-bzip2])
AM_CONFIG_HEADER(config.h)
@@ -43,6 +43,8 @@ GLIB_REQUIRED=2.14.0
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 \
@@ -55,6 +57,18 @@ PKG_CHECK_MODULES(CUPS_PK, glib-2.0 >= $GLIB_REQUIRED \
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)
+AC_SUBST(CUPS_PK_GNOME_LIBS)
+
+# check for cups
+AC_CHECK_HEADERS(cups/cups.h cups/http.h cups/ipp.h)
+CUPS_LIBS=-lcups
+AC_SUBST(CUPS_LIBS)
+
AC_OUTPUT([
Makefile
src/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index bd6e2d3..eaf91cb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,22 +1,45 @@
-INCLUDES = \
+INCLUDES = \
+ $(WARN_CFLAGS) \
+ $(DISABLE_DEPRECATED_CFLAGS) \
$(CUPS_PK_CFLAGS)
-
libexec_PROGRAMS = cups-pk-helper-mechanism
+noinst_PROGRAMS = \
+ test-cups \
+ test-cups-pk
+
cups-pk-helper-mechanism-glue.h: $(srcdir)/cups-pk-helper-mechanism.xml
dbus-binding-tool --prefix=cph_mechanism --mode=glib-server \
--output=cups-pk-helper-mechanism-glue.h \
$(srcdir)/cups-pk-helper-mechanism.xml
cups_pk_helper_mechanism_SOURCES = \
- cups-methods.c \
- cups-methods.h \
+ cups.c \
+ cups.h \
cups-pk-helper-mechanism.c \
cups-pk-helper-mechanism.h \
main.c
cups_pk_helper_mechanism_LDADD = \
- $(CUPS_PK_LIBS)
+ $(CUPS_PK_LIBS) \
+ $(CUPS_LIBS)
+
+test_cups_SOURCES = \
+ cups.c \
+ cups.h \
+ test-cups.c
+test_cups_LDADD = \
+ $(CUPS_PK_LIBS) \
+ $(CUPS_LIBS)
+
+test_cups_pk_SOURCES = \
+ test-cups-pk.c
+test_cups_pk_CFLAGS = \
+ $(CUPS_PK_GNOME_CFLAGS)
+test_cups_pk_LDADD = \
+ $(CUPS_PK_GNOME_LIBS) \
+ $(CUPS_PK_LIBS) \
+ $(CUPS_LIBS)
BUILT_SOURCES = cups-pk-helper-mechanism-glue.h
@@ -25,15 +48,15 @@ dbus_servicesdir = $(datadir)/dbus-1/system-services
dbus_confdir = $(sysconfdir)/dbus-1/system.d
polkitdir = $(datadir)/PolicyKit/policy
-dbus_services_in_files = org.opensuse.cups-pk-helper.Mechanism.service.in
-polkit_in_files = org.opensuse.cups-pk-helper.mechanism.policy.in
+dbus_services_in_files = org.opensuse.CupsPkHelper.Mechanism.service.in
+polkit_in_files = org.opensuse.cupspkhelper.mechanism.policy.in
dbus_services_DATA = $(dbus_services_in_files:.service.in=.service)
$(dbus_services_DATA): $(dbus_services_in_files)
sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@
-dbus_conf_DATA = org.opensuse.cups-pk-helper.Mechanism.conf
+dbus_conf_DATA = org.opensuse.CupsPkHelper.Mechanism.conf
@INTLTOOL_POLICY_RULE@
polkit_DATA = $(polkit_in_files:.policy.in=.policy)
@@ -45,7 +68,7 @@ check:
EXTRA_DIST = \
$(dbus_services_in_files) \
- org.opensuse.cups-pk-helper.Mechanism.conf \
+ org.opensuse.CupsPkHelper.Mechanism.conf \
$(polkit_in_files) \
cups-pk-helper-mechanism.xml
diff --git a/src/cups-methods.c b/src/cups-methods.c
deleted file mode 100644
index e69de29..0000000
--- a/src/cups-methods.c
+++ /dev/null
diff --git a/src/cups-pk-helper-mechanism.c b/src/cups-pk-helper-mechanism.c
index 64f1487..91944e3 100644
--- a/src/cups-pk-helper-mechanism.c
+++ b/src/cups-pk-helper-mechanism.c
@@ -1,4 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et ts=8 sw=8:
*
* Copyright (C) 2008 Novell, Inc.
*
@@ -48,26 +49,29 @@
#include "cups-pk-helper-mechanism.h"
#include "cups-pk-helper-mechanism-glue.h"
+#include "cups.h"
/* exit timer */
static gboolean
do_exit (gpointer user_data)
{
+ g_object_unref (CPH_MECHANISM (user_data));
+
exit (0);
return FALSE;
}
static void
-reset_killtimer (void)
+reset_killtimer (CphMechanism *mechanism)
{
static guint timer_id = 0;
if (timer_id > 0)
g_source_remove (timer_id);
- timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+ timer_id = g_timeout_add_seconds (30, do_exit, mechanism);
}
/* error */
@@ -118,11 +122,23 @@ struct CphMechanismPrivate
{
DBusGConnection *system_bus_connection;
PolKitContext *pol_ctx;
+ CphCups *cups;
};
+static GObject *cph_mechanism_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+static void cph_mechanism_finalize (GObject *object);
+
+
static void
cph_mechanism_class_init (CphMechanismClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = cph_mechanism_constructor;
+ object_class->finalize = cph_mechanism_finalize;
+
g_type_class_add_private (klass, sizeof (CphMechanismPrivate));
dbus_g_object_type_install_info (CPH_TYPE_MECHANISM,
@@ -132,10 +148,53 @@ cph_mechanism_class_init (CphMechanismClass *klass)
CPH_MECHANISM_TYPE_ERROR);
}
+static GObject *
+cph_mechanism_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ CphMechanism *mechanism;
+
+ obj = G_OBJECT_CLASS (cph_mechanism_parent_class)->constructor (
+ type,
+ n_construct_properties,
+ construct_properties);
+
+ mechanism = CPH_MECHANISM (obj);
+ mechanism->priv->cups = cph_cups_new ();
+
+ if (!mechanism->priv->cups) {
+ g_object_unref (mechanism);
+ return NULL;
+ }
+
+ return obj;
+}
+
static void
cph_mechanism_init (CphMechanism *mechanism)
{
mechanism->priv = CPH_MECHANISM_GET_PRIVATE (mechanism);
+
+ mechanism->priv->cups = NULL;
+}
+
+static void
+cph_mechanism_finalize (GObject *object)
+{
+ CphMechanism *mechanism;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CPH_IS_MECHANISM (object));
+
+ mechanism = CPH_MECHANISM (object);
+
+ if (mechanism->priv->cups)
+ g_object_unref (mechanism->priv->cups);
+ mechanism->priv->cups = NULL;
+
+ G_OBJECT_CLASS (cph_mechanism_parent_class)->finalize (object);
}
static gboolean
@@ -210,7 +269,7 @@ register_mechanism (CphMechanism *mechanism)
dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
G_OBJECT (mechanism));
- reset_killtimer ();
+ reset_killtimer (mechanism);
return TRUE;
}
@@ -234,7 +293,7 @@ cph_mechanism_new (void)
static gboolean
_check_polkit_for_action (CphMechanism *mechanism,
DBusGMethodInvocation *context,
- const char *action)
+ const char *action_method)
{
const char *sender;
GError *error;
@@ -242,9 +301,13 @@ _check_polkit_for_action (CphMechanism *mechanism,
PolKitCaller *pk_caller;
PolKitAction *pk_action;
PolKitResult pk_result;
+ char *action;
error = NULL;
+ action = g_strdup_printf ("org.opensuse.cupspkhelper.mechanism.%s",
+ action_method);
+
/* Check that caller is privileged */
sender = dbus_g_method_get_sender (context);
dbus_error_init (&dbus_error);
@@ -263,6 +326,7 @@ _check_polkit_for_action (CphMechanism *mechanism,
dbus_error_free (&dbus_error);
dbus_g_method_return_error (context, error);
g_error_free (error);
+ g_free (action);
return FALSE;
}
@@ -284,11 +348,40 @@ _check_polkit_for_action (CphMechanism *mechanism,
dbus_error_free (&dbus_error);
dbus_g_method_return_error (context, error);
g_error_free (error);
+ g_free (action);
return FALSE;
}
+ g_free (action);
+
return TRUE;
}
/* 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)
+{
+ const char *error;
+
+ reset_killtimer (mechanism);
+
+ if (!_check_polkit_for_action (mechanism, context, "printeradd"))
+ 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 = "";
+
+ 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 ae14a52..c005ad2 100644
--- a/src/cups-pk-helper-mechanism.h
+++ b/src/cups-pk-helper-mechanism.h
@@ -1,4 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et ts=8 sw=8:
*
* Copyright (C) 2008 Novell, Inc.
*
@@ -73,6 +74,14 @@ 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);
+
G_END_DECLS
#endif /* CPH_MECHANISM_H */
diff --git a/src/cups-pk-helper-mechanism.xml b/src/cups-pk-helper-mechanism.xml
index 63975de..74eb4a5 100644
--- a/src/cups-pk-helper-mechanism.xml
+++ b/src/cups-pk-helper-mechanism.xml
@@ -1,5 +1,14 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/">
- <interface name="org.opensuse.cups-pk-helper.Mechanism">
+ <interface name="org.opensuse.CupsPkHelper.Mechanism">
+ <method name="PrinterAdd">
+ <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>
</interface>
</node>
diff --git a/src/cups.c b/src/cups.c
new file mode 100644
index 0000000..018c93e
--- /dev/null
+++ b/src/cups.c
@@ -0,0 +1,683 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et ts=8 sw=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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+
+#include <cups/cups.h>
+#include <cups/http.h>
+#include <cups/ipp.h>
+
+#include "cups.h"
+
+/*
+ getPrinters
+ getDests
+ getClasses
+ getPPDs
+ getServerPPD
+ getDocument
+ getDevices
+ getJobs
+ getJobAttributes
+ ! cancelJob
+ ! cancelAllJobs
+ ! authenticateJob
+ ! setJobHoldUntil
+ ! restartJob
+ getFile
+ putFile
+~! addPrinter
+~! setPrinterDevice
+~! setPrinterInfo
+~! setPrinterLocation
+~! setPrinterShared
+~! setPrinterJobSheets
+~! setPrinterErrorPolicy
+~! setPrinterOpPolicy
+ ! setPrinterUsersAllowed
+ ! setPrinterUsersDenied
+~! addPrinterOptionDefault
+~! deletePrinterOptionDefault
+~! deletePrinter
+ getPrinterAttributes
+ ! addPrinterToClass
+ ! deletePrinterFromClass
+ ! deleteClass
+ getDefault
+~! setDefault
+ getPPD
+~! enablePrinter
+~! disablePrinter
+~! acceptJobs
+~! rejectJobs
+ printTestPage
+ ! adminGetServerSettings
+ ! adminSetServerSettings
+ getSubscriptions
+ createSubscription
+ getNotifications
+ cancelSubscription
+ renewSubscription
+ printFile
+ printFiles
+*/
+
+G_DEFINE_TYPE (CphCups, cph_cups, G_TYPE_OBJECT)
+
+#define CPH_CUPS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CPH_TYPE_CUPS, CphCupsPrivate))
+
+struct CphCupsPrivate
+{
+ http_t *connection;
+ ipp_status_t last_status;
+};
+
+static GObject *cph_cups_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+static void cph_cups_finalize (GObject *object);
+
+
+static void
+cph_cups_class_init (CphCupsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = cph_cups_constructor;
+ object_class->finalize = cph_cups_finalize;
+
+ g_type_class_add_private (klass, sizeof (CphCupsPrivate));
+}
+
+static GObject *
+cph_cups_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ CphCups *cups;
+
+ obj = G_OBJECT_CLASS (cph_cups_parent_class)->constructor (
+ type,
+ n_construct_properties,
+ construct_properties);
+
+ cups = CPH_CUPS (obj);
+
+ cups->priv->connection = httpConnectEncrypt (cupsServer (),
+ ippPort (),
+ cupsEncryption ());
+
+ if (!cups->priv->connection) {
+ g_critical ("Failed to connect to cupsd");
+ g_object_unref (cups);
+ return NULL;
+ }
+
+ return obj;
+}
+
+static void
+cph_cups_init (CphCups *cups)
+{
+ cups->priv = CPH_CUPS_GET_PRIVATE (cups);
+
+ cups->priv->connection = NULL;
+ cups->priv->last_status = IPP_OK;
+}
+
+static void
+cph_cups_finalize (GObject *object)
+{
+ CphCups *cups;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CPH_IS_CUPS (object));
+
+ cups = CPH_CUPS (object);
+
+ if (cups->priv->connection)
+ httpClose (cups->priv->connection);
+ cups->priv->connection = NULL;
+
+ G_OBJECT_CLASS (cph_cups_parent_class)->finalize (object);
+}
+
+CphCups *
+cph_cups_new (void)
+{
+ return g_object_new (CPH_TYPE_CUPS, NULL);
+}
+
+/******************************************************
+ * Validation
+ ******************************************************/
+
+static gboolean
+_cph_cups_is_printer_name_valid (const char *name)
+{
+ if (!name || name[0] == '\0')
+ return FALSE;
+
+ /* FIXME: what's a valid printer name? No space/tabs, etc. */
+ return TRUE;
+}
+
+/******************************************************
+ * Helpers
+ ******************************************************/
+
+static void
+_cph_cups_add_printer_uri (ipp_t *request,
+ const char *name)
+{
+ char uri[HTTP_MAX_URI + 1];
+
+ g_snprintf (uri, sizeof (uri),
+ "ipp://localhost/printers/%s", name);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+}
+
+static void
+_cph_cups_add_class_uri (ipp_t *request,
+ const char *name)
+{
+ char uri[HTTP_MAX_URI + 1];
+
+ g_snprintf (uri, sizeof (uri),
+ "ipp://localhost/classes/%s", name);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+}
+
+static void
+_cph_cups_set_error_from_reply (CphCups *cups,
+ ipp_t *reply)
+{
+ if (reply)
+ cups->priv->last_status = reply->request.status.status_code;
+ else
+ cups->priv->last_status = cupsLastError ();
+}
+
+static gboolean
+_cph_cups_send_request (CphCups *cups,
+ ipp_t *request)
+{
+ gboolean retval;
+ ipp_t *reply;
+
+ reply = cupsDoRequest (cups->priv->connection, request, "/");
+
+ if (!reply || reply->request.status.status_code > IPP_OK_CONFLICT) {
+ retval = FALSE;
+ _cph_cups_set_error_from_reply (cups, reply);
+ } else {
+ retval = TRUE;
+ cups->priv->last_status = IPP_OK;
+ }
+
+ if (reply)
+ ippDelete (reply);
+
+ return retval;
+}
+
+static gboolean
+_cph_cups_send_new_simple_request (CphCups *cups,
+ ipp_op_t op,
+ const char *printer_name)
+{
+ ipp_t *request;
+
+ if (!_cph_cups_is_printer_name_valid (printer_name))
+ /* FIXME: set status */
+ return FALSE;
+
+ request = ippNewRequest (IPP_PAUSE_PRINTER);
+ _cph_cups_add_printer_uri (request, printer_name);
+
+ return _cph_cups_send_request (cups, request);
+}
+
+static gboolean
+_cph_cups_send_new_printer_class_request (CphCups *cups,
+ const char *printer_name,
+ ipp_tag_t group,
+ ipp_tag_t type,
+ const char *name,
+ const char *value)
+{
+ ipp_t *request;
+
+ request = ippNewRequest (CUPS_ADD_MODIFY_PRINTER);
+ _cph_cups_add_printer_uri (request, printer_name);
+ ippAddString (request, group, type, name, NULL, value);
+
+ if (_cph_cups_send_request (cups, request))
+ return TRUE;
+
+ /* it failed, maybe it was a class? */
+ if (cups->priv->last_status != IPP_NOT_POSSIBLE)
+ return FALSE;
+
+ request = ippNewRequest (CUPS_ADD_MODIFY_CLASS);
+ _cph_cups_add_class_uri (request, printer_name);
+ ippAddString (request, group, type, name, NULL, value);
+
+ return _cph_cups_send_request (cups, request);
+}
+
+/******************************************************
+ * Now, the real methods
+ ******************************************************/
+
+const char *
+cph_cups_last_status_to_string (CphCups *cups)
+{
+ g_return_val_if_fail (CPH_IS_CUPS (cups), "");
+
+ return ippErrorString (cups->priv->last_status);
+}
+
+gboolean
+cph_cups_printer_add (CphCups *cups,
+ const char *printer_name,
+ const char *printer_uri,
+ const char *ppd_file,
+ 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);
+
+ /* 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);
+ ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "ppd-name", NULL, ppd_file);
+
+ 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_send_request (cups, request);
+}
+
+gboolean
+cph_cups_printer_delete (CphCups *cups,
+ const char *printer_name)
+{
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ return _cph_cups_send_new_simple_request (cups, CUPS_DELETE_PRINTER,
+ printer_name);
+}
+
+gboolean
+cph_cups_printer_set_default (CphCups *cups,
+ const char *printer_name)
+{
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ return _cph_cups_send_new_simple_request (cups, CUPS_SET_DEFAULT,
+ printer_name);
+}
+
+gboolean
+cph_cups_printer_set_enabled (CphCups *cups,
+ const char *printer_name,
+ gboolean enabled)
+{
+ ipp_op_t op;
+
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ op = enabled ? IPP_RESUME_PRINTER : IPP_PAUSE_PRINTER;
+
+ return _cph_cups_send_new_simple_request (cups, op, printer_name);
+}
+
+gboolean
+cph_cups_printer_set_uri (CphCups *cups,
+ const char *printer_name,
+ const char *printer_uri)
+{
+ 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_URI,
+ "device-uri", NULL, printer_uri);
+
+ return _cph_cups_send_request (cups, request);
+}
+
+/* reason must be NULL if accept is TRUE */
+gboolean
+cph_cups_printer_set_accept_jobs (CphCups *cups,
+ const char *printer_name,
+ gboolean accept,
+ const char *reason)
+{
+ ipp_t *request;
+
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+ g_return_val_if_fail (!accept || reason == NULL, FALSE);
+
+ /* FIXME check arguments are fine */
+
+ if (accept)
+ return _cph_cups_send_new_simple_request (cups,
+ CUPS_ACCEPT_JOBS,
+ printer_name);
+
+ /* !accept */
+ request = ippNewRequest (CUPS_REJECT_JOBS);
+ _cph_cups_add_printer_uri (request, printer_name);
+
+ if (reason)
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
+ "printer-state-message", NULL, reason);
+
+ return _cph_cups_send_request (cups, request);
+}
+
+/* Functions that can work on printer and class */
+
+gboolean
+cph_cups_printer_class_set_info (CphCups *cups,
+ const char *printer_name,
+ const char *info)
+{
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ /* FIXME check arguments are fine */
+
+ return _cph_cups_send_new_printer_class_request (cups, printer_name,
+ IPP_TAG_PRINTER,
+ IPP_TAG_TEXT,
+ "printer-info",
+ info);
+}
+
+gboolean
+cph_cups_printer_class_set_location (CphCups *cups,
+ const char *printer_name,
+ const char *location)
+{
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ /* FIXME check arguments are fine */
+
+ return _cph_cups_send_new_printer_class_request (cups, printer_name,
+ IPP_TAG_PRINTER,
+ IPP_TAG_TEXT,
+ "printer-location",
+ location);
+}
+
+gboolean
+cph_cups_printer_class_set_shared (CphCups *cups,
+ const char *printer_name,
+ gboolean shared)
+{
+ 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);
+ ippAddBoolean (request, IPP_TAG_OPERATION,
+ "printer-is-shared", shared ? 1 : 0);
+
+ if (_cph_cups_send_request (cups, request))
+ return TRUE;
+
+ /* it failed, maybe it was a class? */
+ if (cups->priv->last_status != IPP_NOT_POSSIBLE)
+ return FALSE;
+
+ request = ippNewRequest (CUPS_ADD_MODIFY_CLASS);
+ _cph_cups_add_class_uri (request, printer_name);
+ ippAddBoolean (request, IPP_TAG_OPERATION,
+ "printer-is-shared", shared ? 1 : 0);
+
+ return _cph_cups_send_request (cups, request);
+}
+
+gboolean
+cph_cups_printer_class_set_job_sheets (CphCups *cups,
+ const char *printer_name,
+ const char *start,
+ const char *end)
+{
+ ipp_t *request;
+ const char * const values[2] = { start, end };
+
+ 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);
+ ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-default", 2, NULL, values);
+
+ if (_cph_cups_send_request (cups, request))
+ return TRUE;
+
+ /* it failed, maybe it was a class? */
+ if (cups->priv->last_status != IPP_NOT_POSSIBLE)
+ return FALSE;
+
+ request = ippNewRequest (CUPS_ADD_MODIFY_CLASS);
+ _cph_cups_add_class_uri (request, printer_name);
+ ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-default", 2, NULL, values);
+
+ return _cph_cups_send_request (cups, request);
+}
+
+gboolean
+cph_cups_printer_class_set_error_policy (CphCups *cups,
+ const char *printer_name,
+ const char *policy)
+{
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ /* FIXME check arguments are fine */
+
+ return _cph_cups_send_new_printer_class_request (cups, printer_name,
+ IPP_TAG_PRINTER,
+ IPP_TAG_NAME,
+ "printer-error-policy",
+ policy);
+}
+
+gboolean
+cph_cups_printer_class_set_op_policy (CphCups *cups,
+ const char *printer_name,
+ const char *policy)
+{
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ /* FIXME check arguments are fine */
+
+ return _cph_cups_send_new_printer_class_request (cups, printer_name,
+ IPP_TAG_PRINTER,
+ IPP_TAG_NAME,
+ "printer-op-policy",
+ policy);
+}
+
+/* set first_value to NULL to delete the default */
+gboolean
+cph_cups_printer_class_set_option_default (CphCups *cups,
+ const char *printer_name,
+ const char *option,
+ const char *first_value,
+ ...)
+{
+ char *option_name;
+ const char *value;
+ va_list var_args;
+ GSList *values;
+ int len;
+ ipp_t *request;
+ ipp_attribute_t *attr;
+ gboolean retval;
+
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ /* FIXME check arguments are fine */
+
+ option_name = g_strdup_printf ("%s-default", option);
+
+ /* delete default value for option */
+ if (!first_value) {
+ retval = _cph_cups_send_new_printer_class_request (
+ cups,
+ printer_name,
+ IPP_TAG_PRINTER,
+ IPP_TAG_DELETEATTR,
+ option_name,
+ NULL);
+ g_free (option_name);
+
+ return retval;
+ }
+
+ /* set default vaule for option */
+
+ values = NULL;
+ len = 0;
+ value = first_value;
+ va_start (var_args, first_value);
+
+ while (value) {
+ /* cast to remove warning */
+ values = g_slist_prepend (values, (char *) value);
+ len++;
+ value = va_arg (var_args, char *);
+ }
+
+ va_end (var_args);
+
+ values = g_slist_reverse (values);
+
+ request = ippNewRequest (CUPS_ADD_MODIFY_PRINTER);
+ _cph_cups_add_printer_uri (request, printer_name);
+
+ if (len == 1)
+ ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ option_name, NULL, first_value);
+ else {
+ GSList *value_l;
+ int i;
+
+ attr = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ option_name, len, NULL, NULL);
+
+ i = 0;
+ for (value_l = values; value_l; value_l = value_l->next) {
+ attr->values[i].string.text = g_strdup (value_l->data);
+ i++;
+ }
+ }
+
+ if (_cph_cups_send_request (cups, request)) {
+ retval = TRUE;
+ goto out;
+ }
+
+ /* it failed, maybe it was a class? */
+ if (cups->priv->last_status != IPP_NOT_POSSIBLE) {
+ retval = FALSE;
+ goto out;
+ }
+
+ request = ippNewRequest (CUPS_ADD_MODIFY_CLASS);
+ _cph_cups_add_class_uri (request, printer_name);
+
+ if (len == 1)
+ ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ option_name, NULL, first_value);
+ else {
+ GSList *value_l;
+ int i;
+
+ attr = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ option_name, len, NULL, NULL);
+
+ i = 0;
+ for (value_l = values; value_l; value_l = value_l->next) {
+ attr->values[i].string.text = g_strdup (value_l->data);
+ i++;
+ }
+ }
+
+ retval = _cph_cups_send_request (cups, request);
+
+out:
+ g_free (option_name);
+ g_slist_free (values);
+
+ return retval;
+}
diff --git a/src/cups.h b/src/cups.h
new file mode 100644
index 0000000..f647ca8
--- /dev/null
+++ b/src/cups.h
@@ -0,0 +1,115 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et ts=8 sw=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.
+ *
+ */
+
+#ifndef CPH_CUPS_H
+#define CPH_CUPS_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CPH_TYPE_CUPS (cph_cups_get_type ())
+#define CPH_CUPS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CPH_TYPE_CUPS, CphCups))
+#define CPH_CUPS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CPH_TYPE_CUPS, CphCupsClass))
+#define CPH_IS_CUPS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CPH_TYPE_CUPS))
+#define CPH_IS_CUPS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CPH_TYPE_CUPS))
+#define CPH_CUPS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CPH_TYPE_CUPS, CphCupsClass))
+
+typedef struct CphCupsPrivate CphCupsPrivate;
+
+typedef struct
+{
+ GObject parent;
+ CphCupsPrivate *priv;
+} CphCups;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} CphCupsClass;
+
+GType cph_cups_get_type (void);
+
+CphCups *cph_cups_new (void);
+
+const char *cph_cups_last_status_to_string (CphCups *cups);
+
+gboolean cph_cups_printer_add (CphCups *cups,
+ const char *printer_name,
+ const char *printer_uri,
+ const char *ppd_file,
+ const char *info,
+ const char *location);
+
+gboolean cph_cups_printer_delete (CphCups *cups,
+ const char *printer_name);
+
+gboolean cph_cups_printer_set_default (CphCups *cups,
+ const char *printer_name);
+
+gboolean cph_cups_printer_set_enabled (CphCups *cups,
+ const char *printer_name,
+ gboolean enabled);
+
+gboolean cph_cups_printer_set_uri (CphCups *cups,
+ const char *printer_name,
+ const char *printer_uri);
+
+gboolean cph_cups_printer_set_accept_jobs (CphCups *cups,
+ const char *printer_name,
+ gboolean enabled,
+ const char *reason);
+
+gboolean cph_cups_printer_class_set_info (CphCups *cups,
+ const char *printer_name,
+ const char *info);
+
+gboolean cph_cups_printer_class_set_location (CphCups *cups,
+ const char *printer_name,
+ const char *location);
+
+gboolean cph_cups_printer_class_set_shared (CphCups *cups,
+ const char *printer_name,
+ gboolean shared);
+
+gboolean cph_cups_printer_class_set_job_sheets (CphCups *cups,
+ const char *printer_name,
+ const char *start,
+ const char *end);
+
+gboolean cph_cups_printer_class_set_error_policy (CphCups *cups,
+ const char *printer_name,
+ const char *policy);
+
+gboolean cph_cups_printer_class_set_op_policy (CphCups *cups,
+ const char *printer_name,
+ const char *policy);
+
+gboolean cph_cups_printer_class_set_option_default (CphCups *cups,
+ const char *printer_name,
+ const char *option,
+ const char *first_value,
+ ...);
+G_END_DECLS
+
+#endif /* CPH_CUPS_H */
diff --git a/src/main.c b/src/main.c
index c77ddbd..134c1b0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,4 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et ts=8 sw=8:
*
* Copyright (C) 2008 Novell, Inc.
*
@@ -47,7 +48,7 @@
#include "cups-pk-helper-mechanism.h"
-#define BUS_NAME "org.opensuse.cups-pk-helper.Mechanism"
+#define BUS_NAME "org.opensuse.CupsPkHelper.Mechanism"
static DBusGProxy *
get_bus_proxy (DBusGConnection *connection)
@@ -93,7 +94,6 @@ main (int argc, char **argv)
CphMechanism *mechanism;
DBusGProxy *bus_proxy;
DBusGConnection *connection;
- int ret;
if (!g_thread_supported ())
g_thread_init (NULL);
diff --git a/src/org.opensuse.cups-pk-helper.Mechanism.conf b/src/org.opensuse.CupsPkHelper.Mechanism.conf
index e519ff8..2f47e22 100644
--- a/src/org.opensuse.cups-pk-helper.Mechanism.conf
+++ b/src/org.opensuse.CupsPkHelper.Mechanism.conf
@@ -7,11 +7,13 @@
<!-- Only root can own the service -->
<policy user="root">
- <allow own="org.opensuse.cups-pk-helper.Mechanism"/>
+ <allow own="org.opensuse.CupsPkHelper.Mechanism"/>
+ <allow send_interface="org.opensuse.CupsPkHelper.Mechanism"/>
</policy>
<!-- Allow anyone to invoke methods on the interfaces -->
<policy context="default">
+ <allow send_interface="org.opensuse.CupsPkHelper.Mechanism"/>
</policy>
</busconfig>
diff --git a/src/org.opensuse.cups-pk-helper.Mechanism.service.in b/src/org.opensuse.CupsPkHelper.Mechanism.service.in
index 6751364..87fd6f7 100644
--- a/src/org.opensuse.cups-pk-helper.Mechanism.service.in
+++ b/src/org.opensuse.CupsPkHelper.Mechanism.service.in
@@ -1,4 +1,4 @@
[D-BUS Service]
-Name=org.opensuse.cups-pk-helper.Mechanism
+Name=org.opensuse.CupsPkHelper.Mechanism
Exec=@LIBEXECDIR@/cups-pk-helper-mechanism
User=root
diff --git a/src/org.opensuse.cups-pk-helper.mechanism.policy.in b/src/org.opensuse.cupspkhelper.mechanism.policy.in
index 27b89b7..892309d 100644
--- a/src/org.opensuse.cups-pk-helper.mechanism.policy.in
+++ b/src/org.opensuse.cupspkhelper.mechanism.policy.in
@@ -7,4 +7,13 @@
<vendor>The openSUSE Project</vendor>
<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>
+ <defaults>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
</policyconfig>
diff --git a/src/test-cups-pk.c b/src/test-cups-pk.c
new file mode 100644
index 0000000..ec86a30
--- /dev/null
+++ b/src/test-cups-pk.c
@@ -0,0 +1,178 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et ts=8 sw=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.
+ *
+ */
+
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#define MECHANISM_BUS "org.opensuse.CupsPkHelper.Mechanism"
+
+static gboolean
+do_auth (DBusGConnection *bus,
+ const gchar *action,
+ const gchar *result)
+{
+ DBusGProxy *proxy;
+ GError *error;
+ gboolean ret;
+ gboolean ret_gained_privilege;
+
+ proxy = dbus_g_proxy_new_for_name (bus,
+ "org.freedesktop.PolicyKit.AuthenticationAgent",
+ "/",
+ "org.freedesktop.PolicyKit.AuthenticationAgent");
+
+ if (!proxy)
+ return FALSE;
+
+ error = NULL;
+ ret_gained_privilege = FALSE;
+ ret = dbus_g_proxy_call (proxy, "ObtainAuthorization", &error,
+ G_TYPE_STRING, action, /* action_id */
+ G_TYPE_UINT, 0, /* xid */
+ G_TYPE_UINT, getpid (), /* pid */
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &ret_gained_privilege,
+ G_TYPE_INVALID);
+
+ if (!ret) {
+ g_print ("dbus error: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ return ret_gained_privilege;
+}
+
+static gboolean
+printer_add (DBusGConnection *bus,
+ const char *printer_name,
+ const char *printer_uri,
+ const char *ppd_file,
+ const char *info,
+ const char *location,
+ GError **error)
+{
+ DBusGProxy *proxy;
+ gboolean ret;
+ char *ret_error;
+
+ proxy = dbus_g_proxy_new_for_name (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS);
+
+ if (!proxy)
+ return FALSE;
+
+ *error = NULL;
+ ret_error = NULL;
+
+ ret = dbus_g_proxy_call (proxy, "PrinterAdd", error,
+ G_TYPE_STRING, printer_name,
+ G_TYPE_STRING, printer_uri,
+ G_TYPE_STRING, ppd_file,
+ G_TYPE_STRING, info,
+ G_TYPE_STRING, location,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &ret_error,
+ G_TYPE_INVALID);
+
+ if (ret) {
+ if (!ret_error || ret_error[0] == '\0')
+ g_print ("worked\n");
+ else
+ g_print ("ouch: %s\n", ret_error);
+ }
+
+ return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+ DBusGConnection *system_bus;
+ DBusGConnection *session_bus;
+ gboolean try;
+ gboolean ret;
+ GError *error;
+
+ gtk_init (&argc, &argv);
+
+ error = NULL;
+ system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (system_bus == NULL) {
+ g_warning ("Could not connect to system bus: %s",
+ error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ error = NULL;
+ session_bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (session_bus == NULL) {
+ g_warning ("Could not connect to session bus: %s",
+ error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ try = TRUE;
+ while (try) {
+ try = FALSE;
+ error = NULL;
+ ret = printer_add (system_bus,
+ "MyPrinter", "smb://really/cool",
+ "HP/Business_Inkjet_2200-chp2200.ppd.gz",
+ "This is my printer", "At home",
+ &error);
+
+ if (!ret) {
+ if (dbus_g_error_has_name (error, MECHANISM_BUS".NotPrivileged")) {
+ gchar **tokens;
+
+ 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 */
+ try = do_auth (session_bus, tokens[0], tokens[1]);
+ if (!try)
+ g_print ("not authorized\n");
+ } else
+ g_warning ("helper return string malformed");
+ g_strfreev (tokens);
+ } else if (error) {
+ g_print ("dbus error: %s\n", error->message);
+ g_error_free (error);
+ } else
+ g_print ("unknown error\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/src/test-cups.c b/src/test-cups.c
new file mode 100644
index 0000000..e22612a
--- /dev/null
+++ b/src/test-cups.c
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et ts=8 sw=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.
+ *
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "cups.h"
+
+int
+main (int argc, char **argv)
+{
+ CphCups *cups;
+
+ g_type_init ();
+
+ cups = cph_cups_new ();
+
+ if (cups == NULL)
+ 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_class_set_job_sheets (cups, "DesignJet-650C", "none", "none")) {
+ g_print ("worked\n");
+ } else {
+ g_print ("ouch: %s\n", cph_cups_last_status_to_string (cups));
+ }
+
+ g_object_unref (cups);
+
+ return 0;
+}