[gtk: 2/3] printing: Fix getting info for standalone IPP printers



commit a6e3fc2d2f1554211376a9bac6093f5ff264788c
Author: Marek Kasik <mkasik redhat com>
Date:   Thu Dec 12 16:56:37 2019 +0100

    printing: Fix getting info for standalone IPP printers
    
    Create printer name from name of the advertised service
    for standalone IPP printers as opposed to CUPS printers
    advertised via Avahi which get name from their
    resource path.
    This is similar to what cups-filters does.
    
    Pass GtkPrinter class to request for printer info
    so that it does not need to be searched for
    (such search could fail for standalone IPP printers).
    
    https://gitlab.gnome.org/GNOME/gtk/issues/1509

 modules/printbackends/gtkprintbackendcups.c | 135 ++++++++++++++++++----------
 1 file changed, 90 insertions(+), 45 deletions(-)
---
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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]