[gvfs] afp: work on mounting



commit d6c1fa7e6eb5fc02571e0315f004038d7ed11c92
Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
Date:   Mon May 30 22:01:20 2011 +0200

    afp: work on mounting

 daemon/gvfsafpconnection.c |  374 ++++++++++++++++++++++++++++++++------------
 daemon/gvfsafpconnection.h |   80 +++++++++-
 daemon/gvfsbackendafp.c    |  119 ++++++++++++++-
 3 files changed, 465 insertions(+), 108 deletions(-)
---
diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
index 8aa2ed0..be30b9a 100644
--- a/daemon/gvfsafpconnection.c
+++ b/daemon/gvfsafpconnection.c
@@ -20,11 +20,166 @@
  * Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
  */
 
+#include <string.h>
+
 
 #include "gvfsafpconnection.h"
 
 
+/*
+ * GVfsAfpReply
+ */
+struct _GVfsAfpReplyClass
+{
+	GDataInputStreamClass parent_class;
+};
+
+struct _GVfsAfpReply
+{
+	GDataInputStream parent_instance;
+
+  AfpErrorCode error_code;
+};
+
+G_DEFINE_TYPE (GVfsAfpReply, g_vfs_afp_reply, G_TYPE_DATA_INPUT_STREAM);
+
+static void
+g_vfs_afp_reply_init (GVfsAfpReply *object)
+{
+}
+
+static void
+g_vfs_afp_reply_class_init (GVfsAfpReplyClass *klass)
+{
+}
+
+static GVfsAfpReply *
+g_vfs_afp_reply_new (AfpErrorCode error_code, const char *data, gsize len)
+{
+  GVfsAfpReply *reply;
+
+  reply = g_object_new (G_VFS_TYPE_AFP_REPLY,
+                        "base-stream", g_memory_input_stream_new_from_data (data, len, g_free),
+                        NULL);
+
+  reply->error_code = error_code;
+  
+  return reply;
+}
+
+char *
+g_vfs_afp_reply_read_pascal (GVfsAfpReply *reply)
+{
+  GError *err;
+  guint8 strsize;
+  char *str;
+  gboolean res;  
+  gsize bytes_read;
+
+  err = NULL;
+  strsize = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, &err);
+  if (err != NULL)
+  {
+    g_error_free (err);
+    return NULL;
+  }
+
+  str = g_malloc (strsize + 1);
+  res = g_input_stream_read_all (G_INPUT_STREAM (reply), str, strsize,
+                                 &bytes_read, NULL, NULL);
+  if (!res ||  (bytes_read < strsize))
+  {
+    g_free (str);
+    return NULL;
+  }
+
+  str[strsize] = '\0';
+  return str;
+}
+
+gboolean
+g_vfs_afp_reply_seek (GVfsAfpReply *reply, goffset offset, GSeekType type)
+{
+  gsize avail;
+  GMemoryInputStream *mem_stream;
+
+  /* flush buffered data */
+  avail = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (reply));
+  g_input_stream_skip (G_INPUT_STREAM (reply), avail, NULL, NULL);
+  
+  g_object_get (reply, "base-stream", &mem_stream, NULL);
+  
+  return g_seekable_seek (G_SEEKABLE (mem_stream), offset, type, NULL, NULL);
+}
+
+AfpErrorCode
+g_vfs_afp_reply_get_error_code (GVfsAfpReply *reply)
+{
+  return reply->error_code;
+}
+
+/*
+ * GVfsAfpCommand
+ */
+struct _GVfsAfpCommandClass
+{
+	GDataOutputStreamClass parent_class;
+};
+
+struct _GVfsAfpCommand
+{
+	GDataOutputStream parent_instance;
+
+  AfpCommandType type;
+};
+
+G_DEFINE_TYPE (GVfsAfpCommand, g_vfs_afp_command, G_TYPE_DATA_OUTPUT_STREAM);
+
+
+static void
+g_vfs_afp_command_init (GVfsAfpCommand *command)
+{
+}
+
+static void
+g_vfs_afp_command_class_init (GVfsAfpCommandClass *klass)
+{
+}
+
+GVfsAfpCommand *
+g_vfs_afp_command_new (AfpCommandType type)
+{
+  GVfsAfpCommand *command;
+
+  command = g_object_new (G_VFS_TYPE_AFP_COMMAND,
+                          "base-stream", g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
+
+  command->type = type;
+  g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (command), type, NULL, NULL);
+
+  /* pad byte */
+  g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (command), 0, NULL, NULL);
+
+  return command;
+}
+
+void
+g_vfs_afp_command_put_pascal (GVfsAfpCommand *command, char *str)
+{
+  size_t len;
+
+  len = strlen (str);
+  len = (len <= 256) ? len : 256;
+
+  g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (command), len, NULL, NULL);
+  g_output_stream_write (G_OUTPUT_STREAM (command), str, len, NULL, NULL);
+}
+
+
 
+/*
+ * GVfsAfpConnection
+ */
 G_DEFINE_TYPE (GVfsAfpConnection, g_vfs_afp_connection, G_TYPE_OBJECT);
 
 struct _GVfsAfpConnectionPrivate
@@ -47,6 +202,18 @@ typedef enum
   DSI_WRITE         = 6
 } DsiCommand;
 
+typedef struct {
+  guint8 flags;
+  guint8 command;
+  guint16 requestID;
+  union {
+    guint32 errorCode;
+    guint32 writeOffset;
+  };
+  guint32 totalDataLength;
+  guint32 reserved;
+} DSIHeader;
+
 static guint16
 get_request_id (GVfsAfpConnection *afp_connection)
 {
@@ -54,141 +221,150 @@ get_request_id (GVfsAfpConnection *afp_connection)
 
   return priv->request_id++;
 }
+
 static char *
 read_reply_sync (GVfsAfpConnection *afp_connection,
-                 guint8            *flags,
-                 DsiCommand        *command,
-                 guint16           *request_id,
-                 gsize             *len,
+                 DSIHeader         *dsi_header,
                  GCancellable      *cancellable,
                  GError            **error)
 {
   GVfsAfpConnectionPrivate *priv = afp_connection->priv;
-
-  typedef struct {
-    guint8 flags;
-    guint8 command;
-    guint16 requestID;
-    union {
-      guint32 errorCode;
-      guint32 writeOffset;
-    };
-    guint32 totalDataLength;
-    guint32 reserved;
-  } DSIHeader;
   
   GInputStream *input;
-  DSIHeader dsi_header;
-  gsize read_count;
+  gboolean res;
+  gsize read_count, bytes_read;
   char *data;
+
+  g_assert (dsi_header != NULL);
   
   input = g_io_stream_get_input_stream (priv->conn);
 
   read_count = sizeof (DSIHeader);
-  while (read_count > 0)
-  {
-    gsize bytes_read;
-    
-    bytes_read = g_input_stream_read (input,
-                                      &dsi_header + (sizeof (DSIHeader) - read_count),
-                                      read_count, cancellable, error);
-    if (bytes_read == -1)
-      return NULL;
-
-    read_count -= bytes_read;
-  }
-  dsi_header.requestID = GUINT16_FROM_BE (dsi_header.requestID);
-  dsi_header.totalDataLength = GUINT32_FROM_BE (dsi_header.totalDataLength);
-  
-  *flags = dsi_header.flags;
-  *command = dsi_header.command;
-  *request_id = dsi_header.requestID;
+  res = g_input_stream_read_all (input, dsi_header, read_count, &bytes_read,
+                                 NULL, NULL);
+  if (!res || bytes_read < read_count)
+    return NULL;
 
-  data = g_malloc (dsi_header.totalDataLength);
-  read_count = dsi_header.totalDataLength;
-  while (read_count > 0)
-  {
-    gsize bytes_read;
-    
-    bytes_read = g_input_stream_read (input,
-                                      data + (dsi_header.totalDataLength - read_count),
-                                      read_count, cancellable, error);
-    if (bytes_read == -1)
-    {
-      g_free (data);
-      return NULL;
-    }
+  dsi_header->requestID = GUINT16_FROM_BE (dsi_header->requestID);
+  dsi_header->errorCode = GUINT32_FROM_BE (dsi_header->errorCode);
+  dsi_header->totalDataLength = GUINT32_FROM_BE (dsi_header->totalDataLength);
+
+  data = g_malloc (dsi_header->totalDataLength);
+  read_count = dsi_header->totalDataLength;
 
-    read_count -= bytes_read;
+  res = g_input_stream_read_all (input, data, read_count, &bytes_read, cancellable, error);
+  if (!res || bytes_read < read_count)
+  {
+    g_free (data);
+    return NULL;
   }
 
-  *len = dsi_header.totalDataLength;  
   return data;
 }
 
 static gboolean
 send_request_sync (GVfsAfpConnection *afp_connection,
                    DsiCommand        command,
+                   guint32           writeOffset,
                    gsize             len,
                    char              *data,
+                   guint16           *request_id,
                    GCancellable      *cancellable,
                    GError            **error)
 {
   GVfsAfpConnectionPrivate *priv = afp_connection->priv;
 
-  typedef struct {
-    guint8 flags;
-    guint8 command;
-    guint16 requestID;
-    union {
-      guint32 errorCode;
-      guint32 writeOffset;
-    };
-    guint32 totalDataLength;
-    guint32 reserved;
-  } DSIHeader;
-  
   GOutputStream *output;
+  guint16 req_id;
   DSIHeader dsi_header;
-  gsize write_count;
-  
+  gboolean res;
+  gsize write_count, bytes_written;
+
   output = g_io_stream_get_output_stream (priv->conn);
 
+  req_id = get_request_id (afp_connection);
+  if (request_id)
+    *request_id = get_request_id (afp_connection);
+
   dsi_header.flags = 0x00;
   dsi_header.command = command;
-  dsi_header.requestID = GUINT16_TO_BE (get_request_id (afp_connection));
-  dsi_header.writeOffset = 0;
-  dsi_header.totalDataLength = 0; 
+  dsi_header.requestID = GUINT16_TO_BE (req_id);
+  dsi_header.writeOffset = GUINT32_TO_BE (writeOffset);
+  dsi_header.totalDataLength = GUINT32_TO_BE (len); 
   dsi_header.reserved = 0;
 
   write_count = sizeof (DSIHeader);
-  while (write_count > 0)
-  {
-    gsize bytes_written;
+  res = g_output_stream_write_all (output, &dsi_header, write_count,
+                                   &bytes_written, cancellable, error);
+  if (!res || bytes_written < write_count)
+    return FALSE;
 
-    bytes_written = g_output_stream_write (output,
-                                           &dsi_header + (sizeof (DSIHeader) - write_count),
-                                           write_count, cancellable, error);
-    if (bytes_written == -1)
-      return FALSE;
+  if (data == NULL)
+    return TRUE;
+  
+  write_count = len;
+  res = g_output_stream_write_all (output, data, write_count, &bytes_written,
+                                   cancellable, error);
+  if (!res || bytes_written < write_count)
+    return FALSE;
 
-    write_count -= bytes_written;
-  }
+  return TRUE;
+}
 
-  write_count = len;
-  while (write_count > 0)
-  {
-    gsize bytes_written;
+GVfsAfpReply *
+g_vfs_afp_connection_read_reply_sync (GVfsAfpConnection *afp_connection,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+  char *data;
+  DSIHeader dsi_header;
+
+  data = read_reply_sync (afp_connection, &dsi_header, cancellable, error);
+  if (!data)
+    return NULL;
 
-    bytes_written = g_output_stream_write (output, data + (len - write_count),
-                                           write_count, cancellable, error);
-    if (bytes_written == -1)
-      return FALSE;
+  return g_vfs_afp_reply_new (dsi_header.errorCode, data, dsi_header.totalDataLength);
+}
 
-    write_count -= bytes_written;
+gboolean
+g_vfs_afp_connection_send_command_sync (GVfsAfpConnection *afp_connection,
+                                        GVfsAfpCommand    *afp_command,
+                                        GCancellable      *cancellable,
+                                        GError            **error)
+{
+  DsiCommand dsi_command;
+  guint32 writeOffset;
+  GMemoryOutputStream *mem_stream;
+
+  /* set dsi_command */
+  switch (afp_command->type)
+  {
+    case AFP_COMMAND_GET_SRVR_INFO:
+      writeOffset = 0;
+      dsi_command = DSI_GET_STATUS;
+      break;
+
+    case AFP_COMMAND_WRITE:
+      writeOffset = 8;
+      dsi_command = DSI_WRITE;
+      break;
+    case AFP_COMMAND_WRITE_EXT:
+      writeOffset = 20;
+      dsi_command = DSI_WRITE;
+      break;
+
+    default:
+      writeOffset = 0;
+      dsi_command = DSI_COMMAND;
   }
 
-  return TRUE;
+  mem_stream =
+    G_MEMORY_OUTPUT_STREAM(g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (afp_command)));
+  
+  return send_request_sync (afp_connection, dsi_command, writeOffset,
+                            g_memory_output_stream_get_size (mem_stream),
+                            g_memory_output_stream_get_data (mem_stream),
+                            NULL, cancellable, error);
 }
 
 GVfsAfpConnection *
@@ -202,15 +378,12 @@ g_vfs_afp_connection_new (GSocketConnectable *addr,
   GSocketClient *client;
 
   char *reply;
-  guint8 flags;
-  DsiCommand command;
-  guint16 request_id;
-  gsize len;
+  DSIHeader dsi_header;
   guint pos;
-    
+
   afp_connection = g_object_new (G_VFS_TYPE_AFP_CONNECTION, NULL);
   priv = afp_connection->priv;
-  
+
   client = g_socket_client_new ();
   priv->conn = G_IO_STREAM (g_socket_client_connect (client, addr, cancellable, error));
   g_object_unref (client);
@@ -218,17 +391,16 @@ g_vfs_afp_connection_new (GSocketConnectable *addr,
   if (!priv->conn)
     goto error;
 
-  if (!send_request_sync (afp_connection, DSI_OPEN_SESSION, 0, NULL,
+  if (!send_request_sync (afp_connection, DSI_OPEN_SESSION, 0, 0, NULL, NULL,
                           cancellable, error))
     goto error;
 
-  reply = read_reply_sync (afp_connection, &flags, &command, &request_id, &len,
-                           cancellable, error);
+  reply = read_reply_sync (afp_connection, &dsi_header, cancellable, error);
   if (!reply)
     goto error;
 
   pos = 0;
-  while ((len - pos) > 2)
+  while ((dsi_header.totalDataLength - pos) > 2)
   {
     guint8 optionType;
     guint8 optionLength;
@@ -240,13 +412,13 @@ g_vfs_afp_connection_new (GSocketConnectable *addr,
     {
       
       case 0x00:
-        if (optionLength == 4 && (len - pos) >= 4)
+        if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4)
           priv->kRequestQuanta = GUINT32_FROM_BE (*(guint32 *)(reply + pos));
 
         break;
         
       case 0x02:
-        if (optionLength == 4 && (len - pos) >= 4)
+        if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4)
          priv->kServerReplayCacheSize = GUINT32_FROM_BE (*(guint32 *)(reply + pos));
 
         break;
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
index 86df653..47bbf0c 100644
--- a/daemon/gvfsafpconnection.h
+++ b/daemon/gvfsafpconnection.h
@@ -27,6 +27,68 @@
 
 G_BEGIN_DECLS
 
+typedef enum
+{
+  AFP_COMMAND_GET_SRVR_INFO = 15,
+  AFP_COMMAND_LOGIN = 18,
+  AFP_COMMAND_WRITE = 33,
+  AFP_COMMAND_WRITE_EXT = 61
+} AfpCommandType;
+
+typedef enum
+{
+  AFP_ERROR_NONE = 0,
+  AFP_ERROR_NO_MORE_SESSIONS = -1068
+} AfpErrorCode;
+
+/*
+ * GVfsAfpReply
+ */
+#define G_VFS_TYPE_AFP_REPLY             (g_vfs_afp_reply_get_type ())
+#define G_VFS_AFP_REPLY(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_VFS_TYPE_AFP_REPLY, GVfsAfpReply))
+#define G_VFS_AFP_REPLY_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), G_VFS_TYPE_AFP_REPLY, GVfsAfpReplyClass))
+#define G_VFS_IS_AFP_REPLY(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_VFS_TYPE_AFP_REPLY))
+#define G_VFS_IS_AFP_REPLY_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), G_VFS_TYPE_AFP_REPLY))
+#define G_VFS_AFP_REPLY_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), G_VFS_TYPE_AFP_REPLY, GVfsAfpReplyClass))
+
+typedef struct _GVfsAfpReplyClass GVfsAfpReplyClass;
+typedef struct _GVfsAfpReply      GVfsAfpReply;
+
+char *          g_vfs_afp_reply_read_pascal      (GVfsAfpReply *reply);
+gboolean        g_vfs_afp_reply_seek             (GVfsAfpReply *reply, goffset offset, GSeekType type);
+
+AfpErrorCode    g_vfs_afp_reply_get_error_code   (GVfsAfpReply *reply);
+
+GType           g_vfs_afp_reply_get_type         (void) G_GNUC_CONST;
+
+
+/*
+ * GVfsAfpCommand
+ */
+#define G_VFS_TYPE_AFP_COMMAND             (g_vfs_afp_command_get_type ())
+#define G_VFS_AFP_COMMAND(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_VFS_TYPE_AFP_COMMAND, GVfsAfpCommand))
+#define G_VFS_AFP_COMMAND_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), G_VFS_TYPE_AFP_COMMAND, GVfsAfpCommandClass))
+#define G_VFS_IS_AFP_COMMAND(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_VFS_TYPE_AFP_COMMAND))
+#define G_VFS_IS_AFP_COMMAND_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), G_VFS_TYPE_AFP_COMMAND))
+#define G_VFS_AFP_COMMAND_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), G_VFS_TYPE_AFP_COMMAND, GVfsAfpCommandClass))
+
+typedef struct _GVfsAfpCommandClass GVfsAfpCommandClass;
+typedef struct _GVfsAfpCommand GVfsAfpCommand;
+
+
+GVfsAfpCommand* g_vfs_afp_command_new        (AfpCommandType type);
+
+void            g_vfs_afp_command_put_pascal (GVfsAfpCommand *command, char *str);
+
+
+GType           g_vfs_afp_command_get_type (void) G_GNUC_CONST;
+
+
+
+
+/*
+ * GVfsAfpConnection
+ */
 #define G_VFS_TYPE_AFP_CONNECTION             (g_vfs_afp_connection_get_type ())
 #define G_VFS_AFP_CONNECTION(obj)             (G_VFS_TYPE_CHECK_INSTANCE_CAST ((obj), G_VFS_TYPE_VFS_AFP_CONNECTION, GVfsAfpConnection))
 #define G_VFS_AFP_CONNECTION_CLASS(klass)     (G_VFS_TYPE_CHECK_CLASS_CAST ((klass), G_VFS_TYPE_VFS_AFP_CONNECTION, GVfsAfpConnectionClass))
@@ -49,13 +111,21 @@ struct _GVfsAfpConnection
 
   GVfsAfpConnectionPrivate *priv;
 };
-
+  
 GType g_vfs_afp_connection_get_type (void) G_GNUC_CONST;
 
-GVfsAfpConnection *
-g_vfs_afp_connection_new (GSocketConnectable *addr,
-                          GCancellable       *cancellable,
-                          GError             **error);
+GVfsAfpConnection* g_vfs_afp_connection_new               (GSocketConnectable *addr,
+                                                           GCancellable       *cancellable,
+                                                           GError             **error);
+
+gboolean           g_vfs_afp_connection_send_command_sync (GVfsAfpConnection *afp_connection,
+                                                           GVfsAfpCommand    *afp_command,
+                                                           GCancellable      *cancellable,
+                                                           GError            **error);
+
+GVfsAfpReply*      g_vfs_afp_connection_read_reply_sync   (GVfsAfpConnection *afp_connection,
+                                                           GCancellable *cancellable,
+                                                           GError **error);
 G_END_DECLS
 
 #endif /* _GVFSAFPCONNECTION_H_ */
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index c893a5f..6185264 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -23,6 +23,7 @@
 #include <config.h>
 
 #include <stdlib.h>
+#include <glib/gstdio.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 
@@ -56,16 +57,130 @@ do_mount (GVfsBackend *backend,
   GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
 
   GError *err;
+  GVfsAfpCommand *command;
+  GVfsAfpReply *reply;
+
+  guint16 MachineType_offset, AFPVersionCount_offset, UAMCount_offset;
+  guint16 VolumeIconAndMask_offset, Flags;
+  char *ServerName;
+
+  /* UAM */
+  guint8 UAMCount;
+  GSList *UAMS = NULL;
+  guint i;
 
   err = NULL;
   afp_backend->conn = g_vfs_afp_connection_new (afp_backend->addr,
                                                 G_VFS_JOB (job)->cancellable,
                                                 &err);
   if (!afp_backend->conn)
-    g_vfs_job_failed_from_error (G_VFS_JOB (job), err);
+    goto error;
 
-  g_vfs_job_succeeded (G_VFS_JOB (job));
+  command = g_vfs_afp_command_new (AFP_COMMAND_GET_SRVR_INFO);
+  if (!g_vfs_afp_connection_send_command_sync (afp_backend->conn, command,
+                                               G_VFS_JOB (job)->cancellable, &err))
+    goto error;
+
+  reply = g_vfs_afp_connection_read_reply_sync (afp_backend->conn,
+                                                G_VFS_JOB (job)->cancellable,
+                                                &err);
+  if (!reply)
+    goto error;
+
+  MachineType_offset =
+    g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  AFPVersionCount_offset = 
+    g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  UAMCount_offset =
+    g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  VolumeIconAndMask_offset =
+    g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  Flags =
+    g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  
+  ServerName = g_vfs_afp_reply_read_pascal (reply);
+  g_debug ("ServerName: %s\n", ServerName);
+  g_free (ServerName);
+
+  /* Parse Versions */
+  g_vfs_afp_reply_seek (reply, AFPVersionCount_offset, G_SEEK_SET);
+  UAMCount =
+    g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  g_debug ("Versions\n");
+  for (i = 0; i < UAMCount; i++)
+  {
+    char *version;
+
+    version = g_vfs_afp_reply_read_pascal (reply);
+    g_debug ("%d. %s\n",i + 1, version);
+    g_free (version);
+  }
+  
+  /* Parse UAMs */
+  g_vfs_afp_reply_seek (reply, UAMCount_offset, G_SEEK_SET);
+  UAMCount =
+    g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  for (i = 0; i < UAMCount; i++)
+  {
+    char *UAM;
+
+    UAM = g_vfs_afp_reply_read_pascal (reply);
+    UAMS = g_slist_prepend (UAMS, UAM);
+  }
+
+  g_object_unref (reply);
+
+
+  /* Anonymous login */
+  if (!afp_backend->user)
+  {
+    if (!g_slist_find_custom (UAMS, "No User Authent", g_str_equal))
+    {
+      g_slist_free_full (UAMS, g_free);
+      
+      g_vfs_job_failed (G_VFS_JOB (job),
+			  G_IO_ERROR, G_IO_ERROR_FAILED,
+			  _("Failed to mount AFP share (%s)"), "Server doesn't support anonymous login");
+      return;
+    }
+
+    
+  }
+  else
+  {
+    if (g_slist_find_custom (UAMS, "DHX2", g_str_equal))
+    {
+      g_debug ("Diffie-Hellman 2\n");
+    }
+
+    else if (g_slist_find_custom (UAMS, "DHCAST128", g_str_equal))
+    {
+      g_debug ("Diffie-Hellman");
+    }
+
+    else if (g_slist_find_custom (UAMS, "No User Authent", g_str_equal))
+    {
+      g_debug ("Anonymous login");
+    }
+
+    else
+    {
+      g_slist_free_full (UAMS, g_free);
+      
+      g_vfs_job_failed (G_VFS_JOB (job),
+                        G_IO_ERROR, G_IO_ERROR_FAILED,
+                        _("Failed to mount AFP share (%s)"),
+                        "No suitable authentication mechanism found");
+      return;
+    } 
+  }
+
+  g_slist_free_full (UAMS, g_free);
   
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+error:
+  g_vfs_job_failed_from_error (G_VFS_JOB (job), err);
 }
   
 static gboolean



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