diff options
author | Vincent Untz <vuntz@novell.com> | 2008-11-20 17:52:20 +0100 |
---|---|---|
committer | Vincent Untz <vuntz@novell.com> | 2008-11-20 17:52:20 +0100 |
commit | 23eef6329f90e91bd5dadf9f66db4ab3da4b5b78 (patch) | |
tree | 2c75386f7b8d50f4a93af78be0cf06d73a3c0323 | |
parent | 1e69640f8200b74b3bd044ddd046a51220326a69 (diff) |
Implement ClassAddPrinter/ClassDeletePrinter/ClassDelete methods.
-rw-r--r-- | src/cups-pk-helper-mechanism.c | 58 | ||||
-rw-r--r-- | src/cups-pk-helper-mechanism.h | 15 | ||||
-rw-r--r-- | src/cups-pk-helper-mechanism.xml | 20 | ||||
-rw-r--r-- | src/cups.c | 252 | ||||
-rw-r--r-- | src/cups.h | 11 |
5 files changed, 353 insertions, 3 deletions
diff --git a/src/cups-pk-helper-mechanism.c b/src/cups-pk-helper-mechanism.c index 5cca42c..471d80e 100644 --- a/src/cups-pk-helper-mechanism.c +++ b/src/cups-pk-helper-mechanism.c @@ -682,6 +682,64 @@ cph_mechanism_printer_delete (CphMechanism *mechanism, } gboolean +cph_mechanism_class_add_printer (CphMechanism *mechanism, + const char *name, + const char *printer, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_class_add_printer (mechanism->priv->cups, + name, printer); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_class_delete_printer (CphMechanism *mechanism, + const char *name, + const char *printer, + DBusGMethodInvocation *context) +{ + gboolean ret; + + reset_killtimer (mechanism); + + if (!_check_polkit_for_action (mechanism, context, "printeraddremove")) + return FALSE; + + ret = cph_cups_class_delete_printer (mechanism->priv->cups, + name, printer); + _cph_mechanism_return_error (mechanism, context, !ret); + + return TRUE; +} + +gboolean +cph_mechanism_class_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_class_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) diff --git a/src/cups-pk-helper-mechanism.h b/src/cups-pk-helper-mechanism.h index 7864dc0..1f394b5 100644 --- a/src/cups-pk-helper-mechanism.h +++ b/src/cups-pk-helper-mechanism.h @@ -166,6 +166,21 @@ cph_mechanism_printer_delete (CphMechanism *mechanism, DBusGMethodInvocation *context); gboolean +cph_mechanism_class_add_printer (CphMechanism *mechanism, + const char *name, + const char *printer, + DBusGMethodInvocation *context); +gboolean +cph_mechanism_class_delete_printer (CphMechanism *mechanism, + const char *name, + const char *printer, + DBusGMethodInvocation *context); +gboolean +cph_mechanism_class_delete (CphMechanism *mechanism, + const char *name, + DBusGMethodInvocation *context); + +gboolean cph_mechanism_printer_set_default (CphMechanism *mechanism, const char *name, DBusGMethodInvocation *context); diff --git a/src/cups-pk-helper-mechanism.xml b/src/cups-pk-helper-mechanism.xml index 7c23b85..b7f79af 100644 --- a/src/cups-pk-helper-mechanism.xml +++ b/src/cups-pk-helper-mechanism.xml @@ -107,6 +107,26 @@ <arg name="error" direction="out" type="s"/> </method> + <method name="ClassAddPrinter"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="printer" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="ClassDeletePrinter"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="name" direction="in" type="s"/> + <arg name="printer" direction="in" type="s"/> + <arg name="error" direction="out" type="s"/> + </method> + + <method name="ClassDelete"> + <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"/> @@ -76,9 +76,9 @@ ~!+* deletePrinterOptionDefault ~!+* deletePrinter getPrinterAttributes - ! addPrinterToClass - ! deletePrinterFromClass - ! deleteClass +~!+* addPrinterToClass +~!+* deletePrinterFromClass +~!+* deleteClass getDefault ~!+* setDefault getPPD @@ -280,6 +280,23 @@ _cph_cups_is_printer_name_valid (CphCups *cups, return FALSE; } +/* class is similar to printer in terms of validity checks */ +static gboolean +_cph_cups_is_class_name_valid (CphCups *cups, + const char *name) +{ + char *error; + + if (_cph_cups_is_printer_name_valid_internal (name)) + return TRUE; + + error = g_strdup_printf ("\"%s\" is not a valid class name.", name); + _cph_cups_set_internal_status (cups, error); + g_free (error); + + return FALSE; +} + /* This is some text, but we could potentially do more checks. We don't do them * because cups will already do them. * + for the URI, we could check that the scheme is supported and that the @@ -467,6 +484,23 @@ _cph_cups_send_new_simple_request (CphCups *cups, } static gboolean +_cph_cups_send_new_simple_class_request (CphCups *cups, + ipp_op_t op, + const char *class_name, + CphResource resource) +{ + ipp_t *request; + + if (!_cph_cups_is_class_name_valid (cups, class_name)) + return FALSE; + + request = ippNewRequest (op); + _cph_cups_add_class_uri (request, class_name); + + return _cph_cups_send_request (cups, request, resource); +} + +static gboolean _cph_cups_send_new_printer_class_request (CphCups *cups, const char *printer_name, ipp_tag_t group, @@ -494,6 +528,56 @@ _cph_cups_send_new_printer_class_request (CphCups *cups, return _cph_cups_send_request (cups, request, CPH_RESOURCE_ADMIN); } +static int +_cph_cups_class_has_printer (CphCups *cups, + const char *class_name, + const char *printer_name, + ipp_t **reply) +{ + gboolean retval; + const char *resource_char; + ipp_t *request; + ipp_t *internal_reply; + ipp_attribute_t *printer_names; + int i; + + retval = -1; + + if (reply) + *reply = NULL; + + request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES); + _cph_cups_add_class_uri (request, class_name); + resource_char = _cph_cups_get_resource (CPH_RESOURCE_ROOT); + internal_reply = cupsDoRequest (cups->priv->connection, + request, resource_char); + + if (!internal_reply) + return -1; + + printer_names = ippFindAttribute (internal_reply, + "member-names", IPP_TAG_NAME); + + if (!printer_names) + goto out; + + for (i = 0; i < printer_names->num_values; i++) { + if (!g_ascii_strcasecmp (printer_names->values[i].string.text, + printer_name)) { + retval = i; + break; + } + } + +out: + if (reply) + *reply = internal_reply; + else + ippDelete (internal_reply); + + return retval; +} + static gboolean _cph_cups_printer_class_set_users (CphCups *cups, const char *printer_name, @@ -760,6 +844,168 @@ cph_cups_printer_set_accept_jobs (CphCups *cups, return _cph_cups_send_request (cups, request, CPH_RESOURCE_ADMIN); } +/* Functions that work on a class */ + +gboolean +cph_cups_class_add_printer (CphCups *cups, + const char *class_name, + const char *printer_name) +{ + int printer_index; + ipp_t *reply; + ipp_t *request; + int new_len; + ipp_attribute_t *printer_uris; + char printer_uri[HTTP_MAX_URI + 1]; + ipp_attribute_t *attr; + + g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); + + if (!_cph_cups_is_class_name_valid (cups, class_name)) + return FALSE; + if (!_cph_cups_is_printer_name_valid (cups, printer_name)) + return FALSE; + + /* check that the printer is not already in the class */ + printer_index = _cph_cups_class_has_printer (cups, + class_name, printer_name, + &reply); + if (printer_index >= 0) { + char *error; + + if (reply) + ippDelete (reply); + + error = g_strdup_printf ("Printer %s is already in class %s.", + printer_name, class_name); + _cph_cups_set_internal_status (cups, error); + g_free (error); + + return FALSE; + } + + /* add the printer to the class */ + + request = ippNewRequest (CUPS_ADD_CLASS); + _cph_cups_add_class_uri (request, class_name); + + g_snprintf (printer_uri, sizeof (printer_uri), + "ipp://localhost/printers/%s", printer_name); + + /* new length: 1 + what we had before */ + new_len = 1; + if (reply) { + printer_uris = ippFindAttribute (reply, + "member-uris", IPP_TAG_URI); + if (printer_uris) + new_len += printer_uris->num_values; + } else + printer_uris = NULL; + + attr = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_URI, + "member-uris", new_len, + NULL, NULL); + if (printer_uris) { + int i; + + for (i = 0; i < printer_uris->num_values; i++) + attr->values[i].string.text = g_strdup (printer_uris->values[i].string.text); + } + + if (reply) + ippDelete (reply); + + attr->values[new_len - 1].string.text = g_strdup (printer_uri); + + return _cph_cups_send_request (cups, request, CPH_RESOURCE_ADMIN); +} + +gboolean +cph_cups_class_delete_printer (CphCups *cups, + const char *class_name, + const char *printer_name) +{ + int printer_index; + ipp_t *reply; + ipp_t *request; + int new_len; + ipp_attribute_t *printer_uris; + ipp_attribute_t *attr; + int i; + + g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); + + if (!_cph_cups_is_class_name_valid (cups, class_name)) + return FALSE; + if (!_cph_cups_is_printer_name_valid (cups, printer_name)) + return FALSE; + + /* check that the printer is in the class */ + printer_index = _cph_cups_class_has_printer (cups, + class_name, printer_name, + &reply); + /* Note: the second condition (!reply) is only here for safety purpose. + * When it's TRUE, the first one should be TRUE too */ + if (printer_index < 0 || !reply) { + char *error; + + if (reply) + ippDelete (reply); + + error = g_strdup_printf ("Printer %s is not in class %s.", + printer_name, class_name); + _cph_cups_set_internal_status (cups, error); + g_free (error); + + return FALSE; + } + + /* remove the printer from the class */ + + /* new length: -1 + what we had before */ + new_len = -1; + printer_uris = ippFindAttribute (reply, + "member-uris", IPP_TAG_URI); + if (printer_uris) + new_len += printer_uris->num_values; + + /* empty class: we delete it */ + if (new_len <= 0) { + ippDelete (reply); + return cph_cups_class_delete (cups, class_name); + } + + /* printer_uris is not NULL and reply is not NULL */ + + request = ippNewRequest (CUPS_ADD_CLASS); + _cph_cups_add_class_uri (request, class_name); + + attr = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_URI, + "member-uris", new_len, + NULL, NULL); + + /* copy all printers from the class, except the one we remove */ + for (i = 0; i < printer_index; i++) + attr->values[i].string.text = g_strdup (printer_uris->values[i].string.text); + for (i = printer_index + 1; i < printer_uris->num_values; i++) + attr->values[i].string.text = g_strdup (printer_uris->values[i].string.text); + + ippDelete (reply); + + return _cph_cups_send_request (cups, request, CPH_RESOURCE_ADMIN); +} + +gboolean +cph_cups_class_delete (CphCups *cups, + const char *class_name) +{ + g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE); + + return _cph_cups_send_new_simple_class_request (cups, CUPS_DELETE_CLASS, + class_name, + CPH_RESOURCE_ADMIN); +} + /* Functions that can work on printer and class */ gboolean @@ -87,6 +87,17 @@ gboolean cph_cups_printer_set_accept_jobs (CphCups *cups, gboolean enabled, const char *reason); +gboolean cph_cups_class_add_printer (CphCups *cups, + const char *class_name, + const char *printer_name); + +gboolean cph_cups_class_delete_printer (CphCups *cups, + const char *class_name, + const char *printer_name); + +gboolean cph_cups_class_delete (CphCups *cups, + const char *class_name); + gboolean cph_cups_printer_class_set_info (CphCups *cups, const char *printer_name, const char *info); |