[gnome-control-center] printers: Add functions for searching for LPD printers



commit 7eded1afa54d818f362c8692cd66dfb64269b0ff
Author: Marek Kasik <mkasik redhat com>
Date:   Wed Jul 30 15:37:46 2014 +0200

    printers: Add functions for searching for LPD printers
    
    Add pp_host_get_lpd_devices_async() and
    pp_host_get_lpd_devices_finish() functions to PpHost class.
    pp_host_get_lpd_devices_async() starts searching for LPD printer
    on given address.
    The test consist in connection to the default port 515 (or the one
    given by creator of PpHost) of the address and sending a print job
    to it, which in turn returns a status (we test several standard
    queue names).
    We suppose that there is a LPD printer on the address if a buffer
    with zero length is returned (rfc 1179 5.2).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=695564

 panels/printers/pp-host.c  |  222 ++++++++++++++++++++++++++++++++++++++++++++
 panels/printers/pp-host.h  |   10 ++
 panels/printers/pp-utils.h |    3 +-
 3 files changed, 234 insertions(+), 1 deletions(-)
---
diff --git a/panels/printers/pp-host.c b/panels/printers/pp-host.c
index 4ce6652..081a3d2 100644
--- a/panels/printers/pp-host.c
+++ b/panels/printers/pp-host.c
@@ -22,6 +22,8 @@
 
 #include <glib/gi18n.h>
 
+#define BUFFER_LENGTH 1024
+
 struct _PpHostPrivate
 {
   gchar *hostname;
@@ -577,3 +579,223 @@ pp_host_get_jetdirect_devices_finish (PpHost        *host,
 
   return g_task_propagate_pointer (G_TASK (res), error);
 }
+
+static gboolean
+test_lpd_queue (GSocketClient *client,
+                gchar         *address,
+                gint           port,
+                GCancellable  *cancellable,
+                gchar         *queue_name)
+{
+  GSocketConnection *connection;
+  gboolean           result = FALSE;
+  GError            *error = NULL;
+
+  connection = g_socket_client_connect_to_host (client,
+                                                address,
+                                                port,
+                                                cancellable,
+                                                &error);
+
+  if (connection != NULL)
+    {
+      if (G_IS_TCP_CONNECTION (connection))
+        {
+          GOutputStream *output;
+          GInputStream  *input;
+          gssize         bytes_read, bytes_written;
+          gchar          buffer[BUFFER_LENGTH];
+          gint           length;
+
+          output = g_io_stream_get_output_stream (G_IO_STREAM (connection));
+          input = g_io_stream_get_input_stream (G_IO_STREAM (connection));
+
+          /* This LPD command is explained in RFC 1179, section 5.2 */
+          length = g_snprintf (buffer, BUFFER_LENGTH, "\2%s\n", queue_name);
+
+          bytes_written = g_output_stream_write (output,
+                                                 buffer,
+                                                 length,
+                                                 NULL,
+                                                 &error);
+
+          if (bytes_written != -1)
+            {
+              bytes_read = g_input_stream_read (input,
+                                                buffer,
+                                                BUFFER_LENGTH,
+                                                NULL,
+                                                &error);
+
+              if (bytes_read != -1)
+                {
+                  if (bytes_read > 0 && buffer[0] == 0)
+                    {
+                      /* This LPD command is explained in RFC 1179, section 6.1 */
+                      length = g_snprintf (buffer, BUFFER_LENGTH, "\1\n");
+
+                      bytes_written = g_output_stream_write (output,
+                                                             buffer,
+                                                             length,
+                                                             NULL,
+                                                             &error);
+
+                      result = TRUE;
+                    }
+                }
+              else
+                {
+                  g_clear_error (&error);
+                }
+            }
+          else
+            {
+              g_clear_error (&error);
+            }
+        }
+
+      g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
+      g_object_unref (connection);
+    }
+
+  return result;
+}
+
+static void
+_pp_host_get_lpd_devices_thread (GTask        *task,
+                                 gpointer      source_object,
+                                 gpointer      task_data,
+                                 GCancellable *cancellable)
+{
+  GSocketConnection *connection;
+  PpPrintDevice     *device;
+  PpHost            *host = (PpHost *) source_object;
+  PpHostPrivate     *priv = host->priv;
+  GSocketClient     *client;
+  PpDevicesList     *result;
+  GSDData           *data = (GSDData *) task_data;
+  GError            *error = NULL;
+  GList             *candidates = NULL;
+  GList             *iter;
+  gchar             *found_queue = NULL;
+  gchar             *candidate;
+  gchar             *address;
+  gint               port;
+  gint               i;
+
+  if (priv->port == PP_HOST_UNSET_PORT)
+    port = PP_HOST_DEFAULT_LPD_PORT;
+  else
+    port = priv->port;
+
+  address = g_strdup_printf ("%s:%d", priv->hostname, port);
+  if (address == NULL || address[0] == '/')
+    goto out;
+
+  result = data->devices;
+  data->devices = NULL;
+
+  client = g_socket_client_new ();
+
+  connection = g_socket_client_connect_to_host (client,
+                                                address,
+                                                port,
+                                                cancellable,
+                                                &error);
+
+  if (connection != NULL)
+    {
+      g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
+      g_object_unref (connection);
+
+      /* Most of this list is taken from system-config-printer */
+      candidates = g_list_append (candidates, g_strdup ("PASSTHRU"));
+      candidates = g_list_append (candidates, g_strdup ("AUTO"));
+      candidates = g_list_append (candidates, g_strdup ("BINPS"));
+      candidates = g_list_append (candidates, g_strdup ("RAW"));
+      candidates = g_list_append (candidates, g_strdup ("TEXT"));
+      candidates = g_list_append (candidates, g_strdup ("ps"));
+      candidates = g_list_append (candidates, g_strdup ("lp"));
+      candidates = g_list_append (candidates, g_strdup ("PORT1"));
+
+      for (i = 0; i < 8; i++)
+        {
+          candidates = g_list_append (candidates, g_strdup_printf ("LPT%d", i));
+          candidates = g_list_append (candidates, g_strdup_printf ("LPT%d_PASSTHRU", i));
+          candidates = g_list_append (candidates, g_strdup_printf ("COM%d", i));
+          candidates = g_list_append (candidates, g_strdup_printf ("COM%d_PASSTHRU", i));
+        }
+
+      for (i = 0; i < 50; i++)
+        candidates = g_list_append (candidates, g_strdup_printf ("pr%d", i));
+
+      for (iter = candidates; iter != NULL; iter = iter->next)
+        {
+          candidate = (gchar *) iter->data;
+
+          if (test_lpd_queue (client,
+                              address,
+                              port,
+                              cancellable,
+                              candidate))
+            {
+              found_queue = g_strdup (candidate);
+              break;
+            }
+        }
+
+      if (found_queue != NULL)
+        {
+          device = g_new0 (PpPrintDevice, 1);
+          device->device_class = g_strdup ("network");
+          device->device_uri = g_strdup_printf ("lpd://%s:%d/%s",
+                                                priv->hostname,
+                                                port,
+                                                found_queue);
+          /* Translators: The found device is a Line Printer Daemon printer */
+          device->device_name = g_strdup (_("LPD Printer"));
+          device->host_name = g_strdup (priv->hostname);
+          device->host_port = port;
+          device->acquisition_method = ACQUISITION_METHOD_LPD;
+
+          result->devices = g_list_append (result->devices, device);
+        }
+
+      g_list_free_full (candidates, g_free);
+    }
+
+  g_object_unref (client);
+
+out:
+  g_task_return_pointer (task, result, (GDestroyNotify) pp_devices_list_free);
+  g_object_unref (task);
+
+  g_free (address);
+}
+
+void
+pp_host_get_lpd_devices_async (PpHost              *host,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
+{
+  GSDData *data;
+  GTask   *task;
+
+  data = g_new0 (GSDData, 1);
+  data->devices = g_new0 (PpDevicesList, 1);
+
+  task = g_task_new (G_OBJECT (host), cancellable, callback, user_data);
+  g_task_set_task_data (task, data, (GDestroyNotify) gsd_data_free);
+  g_task_run_in_thread (task, _pp_host_get_lpd_devices_thread);
+}
+
+PpDevicesList *
+pp_host_get_lpd_devices_finish (PpHost        *host,
+                                GAsyncResult  *res,
+                                GError       **error)
+{
+  g_return_val_if_fail (g_task_is_valid (res, host), NULL);
+
+  return g_task_propagate_pointer (G_TASK (res), error);
+}
diff --git a/panels/printers/pp-host.h b/panels/printers/pp-host.h
index b5347a5..5483d85 100644
--- a/panels/printers/pp-host.h
+++ b/panels/printers/pp-host.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
 #define PP_HOST_UNSET_PORT               -1
 #define PP_HOST_DEFAULT_IPP_PORT        631
 #define PP_HOST_DEFAULT_JETDIRECT_PORT 9100
+#define PP_HOST_DEFAULT_LPD_PORT        515
 
 typedef struct _PpHost        PpHost;
 typedef struct _PpHostClass   PpHostClass;
@@ -84,6 +85,15 @@ PpDevicesList *pp_host_get_jetdirect_devices_finish   (PpHost               *hos
                                                        GAsyncResult         *result,
                                                        GError              **error);
 
+void           pp_host_get_lpd_devices_async          (PpHost               *host,
+                                                       GCancellable         *cancellable,
+                                                       GAsyncReadyCallback   callback,
+                                                       gpointer              user_data);
+
+PpDevicesList *pp_host_get_lpd_devices_finish         (PpHost               *host,
+                                                       GAsyncResult         *result,
+                                                       GError              **error);
+
 G_END_DECLS
 
 #endif /* __PP_HOST_H__ */
diff --git a/panels/printers/pp-utils.h b/panels/printers/pp-utils.h
index cd7a515..3850976 100644
--- a/panels/printers/pp-utils.h
+++ b/panels/printers/pp-utils.h
@@ -54,7 +54,8 @@ enum
   ACQUISITION_METHOD_SNMP,
   ACQUISITION_METHOD_SAMBA,
   ACQUISITION_METHOD_SAMBA_HOST,
-  ACQUISITION_METHOD_JETDIRECT
+  ACQUISITION_METHOD_JETDIRECT,
+  ACQUISITION_METHOD_LPD
 };
 
 typedef struct


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