diff options
-rw-r--r-- | src/cups-pk-helper-mechanism.c | 26 | ||||
-rw-r--r-- | src/cups-pk-helper-mechanism.xml | 7 | ||||
-rw-r--r-- | src/cups.c | 245 | ||||
-rw-r--r-- | src/cups.h | 4 |
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"/> @@ -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 @@ -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); |