diff --git a/modules/printbackends/gtkprintbackendcups.c b/modules/printbackends/gtkprintbackendcups.c index c47c4bafd4..db8a985d82 100644 --- a/modules/printbackends/gtkprintbackendcups.c +++ b/modules/printbackends/gtkprintbackendcups.c @@ -80,6 +80,7 @@ typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass; #define AVAHI_SERVICE_BROWSER_IFACE "org.freedesktop.Avahi.ServiceBrowser" #define AVAHI_SERVICE_RESOLVER_IFACE "org.freedesktop.Avahi.ServiceResolver" +#define PRINTER_NAME_ALLOWED_CHARACTERS "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" /* define this to see warnings about ignored ppd options */ #undef PRINT_IGNORED_OPTIONS @@ -1964,6 +1965,7 @@ typedef struct gboolean got_printer_type; gboolean remote_printer; gboolean avahi_printer; + gchar *avahi_resource_path; gchar **auth_info_required; gint default_number_up; guchar ipp_version_major; @@ -2406,8 +2408,11 @@ cups_create_printer (GtkPrintBackendCups *cups_backend, cups_printer = gtk_printer_cups_new (info->printer_name, backend, NULL); #endif - cups_printer->device_uri = g_strdup_printf ("/printers/%s", - info->printer_name); + if (info->avahi_printer) + { + cups_printer->device_uri = g_strdup_printf ("/%s", + info->avahi_resource_path); + } /* Check to see if we are looking at a class */ if (info->member_uris) @@ -2665,17 +2670,33 @@ set_default_printer (GtkPrintBackendCups *cups_backend, } } +typedef struct { + GtkPrinterCups *printer; + http_t *http; +} RequestPrinterInfoData; + +static void +request_printer_info_data_free (RequestPrinterInfoData *data) +{ + GTK_NOTE (PRINTING, + g_print ("CUPS Backend: %s\n", G_STRFUNC)); + httpClose (data->http); + g_object_unref (data->printer); + g_free (data); +} + static void cups_request_printer_info_cb (GtkPrintBackendCups *cups_backend, GtkCupsResult *result, gpointer user_data) { - PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo); - GtkPrintBackend *backend = GTK_PRINT_BACKEND (cups_backend); - ipp_attribute_t *attr; - GtkPrinter *printer; - gboolean status_changed = FALSE; - ipp_t *response; + RequestPrinterInfoData *data = (RequestPrinterInfoData *) user_data; + PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo); + GtkPrintBackend *backend = GTK_PRINT_BACKEND (cups_backend); + ipp_attribute_t *attr; + GtkPrinter *printer = g_object_ref (GTK_PRINTER (data->printer)); + gboolean status_changed = FALSE; + ipp_t *response; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %s\n", G_STRFUNC)); @@ -2708,12 +2729,6 @@ cups_request_printer_info_cb (GtkPrintBackendCups *cups_backend, { set_info_state_message (info); - printer = gtk_print_backend_find_printer (backend, info->printer_name); - if (printer != NULL) - g_object_ref (printer); - else - goto done; - if (info->got_printer_type && info->default_printer && cups_backend->avahi_default_printer == NULL) @@ -2761,13 +2776,12 @@ cups_request_printer_info_cb (GtkPrintBackendCups *cups_backend, if (status_changed) g_signal_emit_by_name (GTK_PRINT_BACKEND (backend), "printer-status-changed", printer); - - /* The ref is held by GtkPrintBackend, in add_printer() */ - g_object_unref (printer); } } done: + g_object_unref (printer); + if (!cups_backend->got_default_printer && gtk_print_backend_printer_list_is_done (backend) && cups_backend->avahi_default_printer != NULL) @@ -2779,17 +2793,20 @@ done: } static void -cups_request_printer_info (const gchar *printer_uri, - const gchar *host, - gint port, - GtkPrintBackendCups *backend) +cups_request_printer_info (GtkPrinterCups *printer) { - GtkCupsRequest *request; - http_t *http; + RequestPrinterInfoData *data; + GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (gtk_printer_get_backend (GTK_PRINTER (printer))); + GtkCupsRequest *request; + http_t *http; - http = httpConnect2 (host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); + http = httpConnect2 (printer->hostname, printer->port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); if (http) { + data = g_new0 (RequestPrinterInfoData, 1); + data->http = http; + data->printer = g_object_ref (printer); + request = gtk_cups_request_new_with_username (http, GTK_CUPS_POST, IPP_GET_PRINTER_ATTRIBUTES, @@ -2801,7 +2818,7 @@ cups_request_printer_info (const gchar *printer_uri, gtk_cups_request_set_ipp_version (request, 1, 1); gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, printer_uri); + "printer-uri", NULL, printer->printer_uri); gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", G_N_ELEMENTS (printer_attrs_detailed), @@ -2810,8 +2827,8 @@ cups_request_printer_info (const gchar *printer_uri, cups_request_execute (backend, request, (GtkPrintCupsResponseCallbackFunc) cups_request_printer_info_cb, - http, - (GDestroyNotify) httpClose); + data, + (GDestroyNotify) request_printer_info_data_free); } } @@ -2823,6 +2840,7 @@ typedef struct gint port; gchar *printer_name; gchar *name; + gchar *resource_path; gboolean got_printer_type; guint printer_type; gboolean got_printer_state; @@ -2887,6 +2905,7 @@ create_cups_printer_from_avahi_data (AvahiConnectionTestData *data) info->avahi_printer = TRUE; info->printer_name = data->printer_name; info->printer_uri = data->printer_uri; + info->avahi_resource_path = data->resource_path; info->default_printer = FALSE; info->remote_printer = TRUE; info->is_accepting_jobs = TRUE; @@ -2923,7 +2942,6 @@ create_cups_printer_from_avahi_data (AvahiConnectionTestData *data) set_info_state_message (info); printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (data->backend), data->printer_name); - if (printer == NULL && data->UUID != NULL) printer = find_printer_by_uuid (data->backend, data->UUID); @@ -2947,6 +2965,7 @@ create_cups_printer_from_avahi_data (AvahiConnectionTestData *data) GTK_PRINTER_CUPS (printer)->avahi_name = g_strdup (data->name); GTK_PRINTER_CUPS (printer)->avahi_type = g_strdup (data->type); GTK_PRINTER_CUPS (printer)->avahi_domain = g_strdup (data->domain); + GTK_PRINTER_CUPS (printer)->printer_uri = g_strdup (data->printer_uri); g_free (GTK_PRINTER_CUPS (printer)->hostname); GTK_PRINTER_CUPS (printer)->hostname = g_strdup (data->host); GTK_PRINTER_CUPS (printer)->port = data->port; @@ -3000,6 +3019,7 @@ avahi_connection_test_cb (GObject *source_object, g_free (data->host); g_free (data->printer_name); g_free (data->name); + g_free (data->resource_path); g_free (data->type); g_free (data->domain); g_free (data); @@ -3051,9 +3071,10 @@ avahi_service_resolver_cb (GObject *source_object, guint32 flags; guint16 port; GError *error = NULL; - gchar *queue_name = NULL; gchar *tmp; gchar *printer_name; + gchar **printer_name_strv; + gchar **printer_name_compressed_strv; gchar *endptr; gchar *key; gchar *value; @@ -3061,7 +3082,7 @@ avahi_service_resolver_cb (GObject *source_object, gint interface; gint protocol; gint aprotocol; - gint i; + gint i, j; output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, @@ -3103,13 +3124,7 @@ avahi_service_resolver_cb (GObject *source_object, if (g_strcmp0 (key, "rp") == 0) { - queue_name = g_strdup (value); - - printer_name = g_strrstr (queue_name, "/"); - if (printer_name != NULL) - data->printer_name = g_strdup (printer_name + 1); - else - data->printer_name = g_strdup (queue_name); + data->resource_path = g_strdup (value); } else if (g_strcmp0 (key, "note") == 0) { @@ -3145,17 +3160,51 @@ avahi_service_resolver_cb (GObject *source_object, } } - if (queue_name) + if (data->resource_path != NULL) { + if (data->got_printer_type && + (g_strcmp0 (data->resource_path, "printers/") == 0 || + g_strcmp0 (data->resource_path, "classes/") == 0)) + { + /* This is a CUPS printer advertised via Avahi */ + printer_name = g_strrstr (data->resource_path, "/"); + if (printer_name != NULL && printer_name[0] != '\0') + data->printer_name = g_strdup (printer_name + 1); + else + data->printer_name = g_strdup (data->resource_path); + } + else + { + printer_name = g_strdup (name); + g_strcanon (printer_name, PRINTER_NAME_ALLOWED_CHARACTERS, '-'); + + printer_name_strv = g_strsplit_set (printer_name, "-", -1); + printer_name_compressed_strv = g_new0 (gchar *, g_strv_length (printer_name_strv)); + for (i = 0, j = 0; printer_name_strv[i] != NULL; i++) + { + if (printer_name_strv[i][0] != '\0') + { + printer_name_compressed_strv[j] = printer_name_strv[i]; + j++; + } + } + + data->printer_name = g_strjoinv ("-", printer_name_compressed_strv); + + g_strfreev (printer_name_strv); + g_free (printer_name_compressed_strv); + g_free (printer_name); + } + if (g_strcmp0 (type, "_ipp._tcp") == 0) protocol_string = "ipp"; else protocol_string = "ipps"; if (aprotocol == AVAHI_PROTO_INET6) - data->printer_uri = g_strdup_printf ("%s://[%s]:%u/%s", protocol_string, address, port, queue_name); + data->printer_uri = g_strdup_printf ("%s://[%s]:%u/%s", protocol_string, address, port, data->resource_path); else - data->printer_uri = g_strdup_printf ("%s://%s:%u/%s", protocol_string, address, port, queue_name); + data->printer_uri = g_strdup_printf ("%s://%s:%u/%s", protocol_string, address, port, data->resource_path); data->host = g_strdup (address); data->port = port; @@ -3172,7 +3221,6 @@ avahi_service_resolver_cb (GObject *source_object, backend->avahi_cancellable, avahi_connection_test_cb, data); - g_free (queue_name); } else { @@ -3811,10 +3859,7 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend, if (cups_printer->request_original_uri) cups_printer->request_original_uri = FALSE; - cups_request_printer_info (cups_printer->printer_uri, - cups_printer->hostname, - cups_printer->port, - GTK_PRINT_BACKEND_CUPS (gtk_printer_get_backend (printer))); + cups_request_printer_info (cups_printer); } return;