summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Hatina <mhatina@redhat.com>2015-11-10 10:12:36 +0100
committerMarek Kasik <mkasik@redhat.com>2015-11-12 12:00:36 +0100
commit18320ba204b9a1dec4d4c668b61a4ab980417507 (patch)
treeb74877cdd1897112ac09bc790136cfe2d8fbd94b
parentd013b617fe21117913a1c7c517ed6774ef2759ca (diff)
Add function for printer renaming
New method PrinterRename for printer renaming, it actually deletes old printer and add new one. It is also possible to rename classes and their members. https://bugs.freedesktop.org/show_bug.cgi?id=92463
-rw-r--r--src/cups-pk-helper-mechanism.c26
-rw-r--r--src/cups-pk-helper-mechanism.xml7
-rw-r--r--src/cups.c245
-rw-r--r--src/cups.h4
4 files changed, 282 insertions, 0 deletions
diff --git a/src/cups-pk-helper-mechanism.c b/src/cups-pk-helper-mechanism.c
index a468a2a..0e07349 100644
--- a/src/cups-pk-helper-mechanism.c
+++ b/src/cups-pk-helper-mechanism.c
@@ -903,6 +903,28 @@ cph_mechanism_printer_delete (CphIfaceMechanism *object,
}
static gboolean
+cph_mechanism_printer_class_rename (CphIfaceMechanism *object,
+ GDBusMethodInvocation *context,
+ const char *old_printer_name,
+ const char *new_printer_name)
+{
+ CphMechanism *mechanism = CPH_MECHANISM (object);
+ gboolean ret;
+
+ _cph_mechanism_emit_called (mechanism);
+
+ if (!_check_polkit_for_printer_class (mechanism, context, old_printer_name))
+ return TRUE;
+
+ ret = cph_cups_printer_class_rename (mechanism->priv->cups, old_printer_name, new_printer_name);
+
+ cph_iface_mechanism_complete_printer_rename (
+ object, context,
+ _cph_mechanism_return_error (mechanism, !ret));
+ return TRUE;
+}
+
+static gboolean
cph_mechanism_class_add_printer (CphIfaceMechanism *object,
GDBusMethodInvocation *context,
const char *name,
@@ -1488,6 +1510,10 @@ cph_mechanism_connect_signals (CphMechanism *mechanism)
G_CALLBACK (cph_mechanism_printer_delete_option_default),
NULL);
g_signal_connect (mechanism,
+ "handle-printer-rename",
+ G_CALLBACK (cph_mechanism_printer_class_rename),
+ NULL);
+ g_signal_connect (mechanism,
"handle-printer-set-accept-jobs",
G_CALLBACK (cph_mechanism_printer_set_accept_jobs),
NULL);
diff --git a/src/cups-pk-helper-mechanism.xml b/src/cups-pk-helper-mechanism.xml
index b3c5f7f..ad4357c 100644
--- a/src/cups-pk-helper-mechanism.xml
+++ b/src/cups-pk-helper-mechanism.xml
@@ -92,6 +92,13 @@
<arg name="error" direction="out" type="s"/>
</method>
+ <method name="PrinterRename">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="old_name" direction="in" type="s"/>
+ <arg name="new_name" 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"/>
diff --git a/src/cups.c b/src/cups.c
index 92425eb..2b69cab 100644
--- a/src/cups.c
+++ b/src/cups.c
@@ -611,6 +611,22 @@ _cph_cups_add_printer_uri (ipp_t *request,
}
static void
+_cph_cups_add_job_printer_uri (ipp_t *request,
+ const char *name)
+{
+ char *escaped_name;
+ char uri[HTTP_MAX_URI + 1];
+
+ escaped_name = g_uri_escape_string (name, NULL, FALSE);
+ g_snprintf (uri, sizeof (uri),
+ "ipp://localhost/printers/%s", escaped_name);
+ g_free (escaped_name);
+
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-printer-uri", NULL, uri);
+}
+
+static void
_cph_cups_add_class_uri (ipp_t *request,
const char *name)
{
@@ -2088,6 +2104,235 @@ cph_cups_class_delete (CphCups *cups,
CPH_RESOURCE_ADMIN);
}
+gboolean
+cph_cups_printer_class_rename (CphCups *cups,
+ const char *old_printer_name,
+ const char *new_printer_name)
+{
+ cups_dest_t *dests;
+ cups_dest_t *dest;
+ cups_job_t *jobs;
+ int num_dests = 0;
+ int num_jobs = 0;
+ ipp_t *request;
+ ipp_t *response;
+ ipp_t *reply;
+ ipp_attribute_t *attr;
+ gchar *device_uri = NULL;
+ gchar *printer_info = NULL;
+ gchar *job_sheets = NULL;
+ gchar *printer_location = NULL;
+ gchar *printer_uri = NULL;
+ gchar *error_policy = NULL;
+ gchar *op_policy = NULL;
+ gchar **users_allowed = NULL;
+ gchar **users_denied = NULL;
+ gchar **member_names = NULL;
+ const gchar *ppd_link = NULL;
+ gchar *ppd_filename = NULL;
+ gchar **sheets = NULL;
+ gchar *start_sheet = NULL;
+ gchar *end_sheet = NULL;
+ gboolean accepting = FALSE;
+ gboolean printer_shared = FALSE;
+ gboolean printer_paused = FALSE;
+ gboolean is_default = FALSE;
+ int i;
+
+ static const char * const requested_attrs[] = {
+ "printer-error-policy",
+ "printer-op-policy",
+ "requesting-user-name-allowed",
+ "requesting-user-name-denied",
+ "member-names"
+ };
+
+ g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
+
+ if (!_cph_cups_is_printer_name_valid (cups, old_printer_name))
+ return FALSE;
+ if (!_cph_cups_is_printer_name_valid (cups, new_printer_name))
+ return FALSE;
+
+ num_dests = cupsGetDests (&dests);
+
+ dest = cupsGetDest (new_printer_name, NULL, num_dests, dests);
+ if (dest != NULL) {
+ cupsFreeDests (num_dests, dests);
+ return FALSE;
+ }
+
+ dest = cupsGetDest (old_printer_name, NULL, num_dests, dests);
+ if (dest == NULL) {
+ cupsFreeDests (num_dests, dests);
+ return FALSE;
+ }
+
+ num_jobs = cupsGetJobs (&jobs, old_printer_name, 0, CUPS_WHICHJOBS_ACTIVE);
+ for (i = 0; i < num_jobs; i++) {
+ if (jobs[i].state == IPP_JSTATE_PENDING ||
+ jobs[i].state == IPP_JSTATE_PROCESSING) {
+ cupsFreeJobs (num_jobs, jobs);
+ cupsFreeDests (num_dests, dests);
+ return FALSE;
+ }
+ }
+ cupsFreeJobs (num_jobs, jobs);
+
+ for (i = 0; i < dest->num_options; i++) {
+ if (g_strcmp0 (dest->options[i].name, "device-uri") == 0) {
+ device_uri = dest->options[i].value;
+ } else if (g_strcmp0 (dest->options[i].name, "job-sheets") == 0) {
+ job_sheets = dest->options[i].value;
+ } else if (g_strcmp0 (dest->options[i].name, "printer-info") == 0) {
+ printer_info = dest->options[i].value;
+ } else if (g_strcmp0 (dest->options[i].name, "printer-is-accepting-jobs") == 0) {
+ accepting = g_strcmp0 (dest->options[i].value, "true") == 0;
+ } else if (g_strcmp0 (dest->options[i].name, "printer-is-shared") == 0) {
+ printer_shared = g_strcmp0 (dest->options[i].value, "true") == 0;
+ } else if (g_strcmp0 (dest->options[i].name, "printer-location") == 0) {
+ printer_location = dest->options[i].value;
+ } else if (g_strcmp0 (dest->options[i].name, "printer-state") == 0) {
+ printer_paused = g_strcmp0 (dest->options[i].value, "5") == 0;
+ } else if (g_strcmp0 (dest->options[i].name, "printer-uri-supported") == 0) {
+ printer_uri = dest->options[i].value;
+ }
+ }
+ is_default = dest->is_default;
+
+ request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+ ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", G_N_ELEMENTS (requested_attrs), NULL, requested_attrs);
+ response = cupsDoRequest (cups->priv->connection, request, "/");
+
+ if (response != NULL) {
+ if (ippGetStatusCode (response) <= IPP_OK_CONFLICT) {
+ attr = ippFindAttribute (response, "printer-error-policy", IPP_TAG_NAME);
+ if (attr != NULL)
+ error_policy = g_strdup (ippGetString (attr, 0, NULL));
+
+ attr = ippFindAttribute (response, "printer-op-policy", IPP_TAG_NAME);
+ if (attr != NULL)
+ op_policy = g_strdup (ippGetString (attr, 0, NULL));
+
+ attr = ippFindAttribute (response, "requesting-user-name-allowed", IPP_TAG_NAME);
+ if (attr != NULL && ippGetCount (attr) > 0) {
+ users_allowed = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (i = 0; i < ippGetCount (attr); i++)
+ users_allowed[i] = g_strdup (ippGetString (attr, i, NULL));
+ }
+
+ attr = ippFindAttribute (response, "requesting-user-name-denied", IPP_TAG_NAME);
+ if (attr != NULL && ippGetCount (attr) > 0) {
+ users_denied = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (i = 0; i < ippGetCount (attr); i++)
+ users_denied[i] = g_strdup (ippGetString (attr, i, NULL));
+ }
+
+ attr = ippFindAttribute (response, "member-names", IPP_TAG_NAME);
+ if (attr != NULL && ippGetCount (attr) > 0) {
+ member_names = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (i = 0; i < ippGetCount (attr); i++)
+ member_names[i] = g_strdup (ippGetString (attr, i, NULL));
+ }
+ }
+ ippDelete (response);
+ }
+
+ ppd_link = cupsGetPPD (old_printer_name);
+ if (ppd_link != NULL && (ppd_filename = g_file_read_link (ppd_link, NULL)) == NULL) {
+ ppd_filename = g_strdup (ppd_link);
+ }
+
+ if (cph_cups_is_class (cups, old_printer_name)) {
+ if (member_names != NULL) {
+ for (i = 0; i < g_strv_length (member_names); i++) {
+ cph_cups_class_add_printer (cups, new_printer_name, member_names[i]);
+ }
+ }
+ } else if (cph_cups_printer_add_with_ppd_file (cups,
+ new_printer_name,
+ device_uri,
+ ppd_filename,
+ printer_info,
+ printer_location)) {
+ for (i = 0; i < num_dests; i++) {
+ if (cph_cups_is_class (cups, dests[i].name)) {
+ if (_cph_cups_class_has_printer (cups, dests[i].name, old_printer_name, &reply) >= 0) {
+ if (reply != NULL)
+ ippDelete (reply);
+ cph_cups_class_delete_printer (cups, dests[i].name, old_printer_name);
+ cph_cups_class_add_printer (cups, dests[i].name, new_printer_name);
+ }
+ }
+ }
+ } else {
+ cph_cups_printer_set_accept_jobs (cups, old_printer_name, accepting, NULL);
+ return FALSE;
+ }
+
+ num_jobs = cupsGetJobs (&jobs, old_printer_name, 0, CUPS_WHICHJOBS_ACTIVE);
+ for (i = 0; i < num_jobs; i++) {
+ if (jobs[i].state == IPP_JSTATE_HELD) {
+ request = ippNewRequest (CUPS_MOVE_JOB);
+
+ _cph_cups_add_job_uri (request, jobs[i].id);
+ _cph_cups_add_job_printer_uri (request, new_printer_name);
+ _cph_cups_add_requesting_user_name (request, cupsUser ());
+ _cph_cups_send_request (cups, request, CPH_RESOURCE_JOBS);
+ }
+ }
+ cupsFreeJobs (num_jobs, jobs);
+
+ cph_cups_printer_set_accept_jobs (cups, new_printer_name, accepting, NULL);
+ if (is_default)
+ cph_cups_printer_set_default (cups, new_printer_name);
+ cph_cups_printer_class_set_error_policy (cups, new_printer_name, error_policy);
+ cph_cups_printer_class_set_op_policy (cups, new_printer_name, op_policy);
+
+ if (job_sheets != NULL) {
+ sheets = g_strsplit (job_sheets, ",", 0);
+ if (g_strv_length (sheets) > 1) {
+ start_sheet = sheets[0];
+ end_sheet = sheets[1];
+ }
+ cph_cups_printer_class_set_job_sheets (cups, new_printer_name, start_sheet, end_sheet);
+ }
+ cph_cups_printer_set_enabled (cups, new_printer_name, !printer_paused);
+ cph_cups_printer_class_set_shared (cups, new_printer_name, printer_shared);
+ cph_cups_printer_class_set_users_allowed (cups, new_printer_name, (const char * const *) users_allowed);
+ cph_cups_printer_class_set_users_denied (cups, new_printer_name, (const char * const *) users_denied);
+
+ if (cph_cups_is_class (cups, old_printer_name)) {
+ if (member_names != NULL) {
+ for (i = 0; i < g_strv_length (member_names); i++) {
+ cph_cups_class_delete_printer (cups, old_printer_name, member_names[i]);
+ }
+ }
+
+ cph_cups_class_delete (cups, old_printer_name);
+ } else {
+ cph_cups_printer_delete (cups, old_printer_name);
+ }
+
+
+ cupsFreeDests (num_dests, dests);
+
+ if (ppd_link != NULL) {
+ g_unlink (ppd_link);
+ g_free (ppd_filename);
+ }
+ g_free (op_policy);
+ g_free (error_policy);
+ g_strfreev (sheets);
+ g_strfreev (users_allowed);
+ g_strfreev (users_denied);
+
+ return TRUE;
+}
+
/* Functions that can work on printer and class */
gboolean
diff --git a/src/cups.h b/src/cups.h
index 3017792..a548e49 100644
--- a/src/cups.h
+++ b/src/cups.h
@@ -137,6 +137,10 @@ gboolean cph_cups_class_delete_printer (CphCups *cups,
gboolean cph_cups_class_delete (CphCups *cups,
const char *class_name);
+gboolean cph_cups_printer_class_rename (CphCups *cups,
+ const char *old_printer_name,
+ const char *new_printer_name);
+
gboolean cph_cups_printer_class_set_info (CphCups *cups,
const char *printer_name,
const char *info);