[gvfs] [FTP] add EPRT support



commit 19a6bf345fdb8d445e4c3683e4ca0af0a0031f0b
Author: Benjamin Otte <otte gnome org>
Date:   Tue Jun 16 11:16:27 2009 +0200

    [FTP] add EPRT support
    
    The code does not support some corner cases that are listed in the RFC
    (see inline comments), but I suspect those will never be hit. We can add
    those when they are hit.

 daemon/gvfsftptask.c |   60 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 53 insertions(+), 7 deletions(-)
---
diff --git a/daemon/gvfsftptask.c b/daemon/gvfsftptask.c
index 318dde4..9cab5a8 100644
--- a/daemon/gvfsftptask.c
+++ b/daemon/gvfsftptask.c
@@ -876,7 +876,52 @@ g_vfs_ftp_task_setup_data_connection_pasv (GVfsFtpTask *task, GVfsFtpMethod meth
 }
 
 static GVfsFtpMethod
-g_vfs_ftp_task_open_data_connection_port (GVfsFtpTask *task, GVfsFtpMethod unused)
+g_vfs_ftp_task_setup_data_connection_eprt (GVfsFtpTask *task, GVfsFtpMethod unused)
+{
+  GSocketAddress *addr;
+  guint status, port, family;
+  char *ip_string;
+
+  /* workaround for the task not having a connection yet */
+  if (task->conn == NULL &&
+      g_vfs_ftp_task_send (task, 0, "NOOP") == 0)
+    return G_VFS_FTP_METHOD_ANY;
+
+  addr = g_vfs_ftp_connection_listen_data_connection (task->conn, &task->error);
+  if (addr == NULL)
+    return G_VFS_FTP_METHOD_ANY;
+  switch (g_socket_address_get_family (addr))
+    {
+      case G_SOCKET_FAMILY_IPV4:
+        family = 1;
+        break;
+      case G_SOCKET_FAMILY_IPV6:
+        family = 2;
+        break;
+      default:
+        g_object_unref (addr);
+        return G_VFS_FTP_METHOD_ANY;
+    }
+
+  ip_string = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)));
+  /* if this ever happens (and it must not for IP4 and IP6 addresses), 
+   * we need to add support for using a different separator */
+  g_assert (strchr (ip_string, '|') == NULL);
+  port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
+
+  /* we could handle the 522 response here, (unsupported network family),
+   * but I don't think that will buy us anything */
+  status = g_vfs_ftp_task_send (task, 0, "EPRT |%u|%s|%u|", family, ip_string, port);
+  g_free (ip_string);
+  g_object_unref (addr);
+  if (status == 0)
+    return G_VFS_FTP_METHOD_ANY;
+  
+  return G_VFS_FTP_METHOD_EPRT;
+}
+
+static GVfsFtpMethod
+g_vfs_ftp_task_setup_data_connection_port (GVfsFtpTask *task, GVfsFtpMethod unused)
 {
   GSocketAddress *addr;
   guint status, i, port;
@@ -925,7 +970,8 @@ g_vfs_ftp_task_setup_data_connection_any (GVfsFtpTask *task, GVfsFtpMethod unuse
   } funcs_ordered[] = {
     { G_VFS_FTP_FEATURE_EPSV, g_vfs_ftp_task_setup_data_connection_epsv },
     { 0,                      g_vfs_ftp_task_setup_data_connection_pasv },
-    { 0,                      g_vfs_ftp_task_open_data_connection_port }
+    { G_VFS_FTP_FEATURE_EPSV, g_vfs_ftp_task_setup_data_connection_eprt },
+    { 0,                      g_vfs_ftp_task_setup_data_connection_port }
   };
   GVfsFtpMethod method;
   guint i;
@@ -974,12 +1020,12 @@ void
 g_vfs_ftp_task_setup_data_connection (GVfsFtpTask *task)
 {
   static const GVfsFtpOpenDataConnectionFunc connect_funcs[] = {
-    [G_VFS_FTP_METHOD_ANY] = g_vfs_ftp_task_setup_data_connection_any,
-    [G_VFS_FTP_METHOD_EPSV] = g_vfs_ftp_task_setup_data_connection_epsv,
-    [G_VFS_FTP_METHOD_PASV] = g_vfs_ftp_task_setup_data_connection_pasv,
+    [G_VFS_FTP_METHOD_ANY]       = g_vfs_ftp_task_setup_data_connection_any,
+    [G_VFS_FTP_METHOD_EPSV]      = g_vfs_ftp_task_setup_data_connection_epsv,
+    [G_VFS_FTP_METHOD_PASV]      = g_vfs_ftp_task_setup_data_connection_pasv,
     [G_VFS_FTP_METHOD_PASV_ADDR] = g_vfs_ftp_task_setup_data_connection_pasv,
-    [G_VFS_FTP_METHOD_EPRT] = NULL,
-    [G_VFS_FTP_METHOD_PORT] = g_vfs_ftp_task_open_data_connection_port
+    [G_VFS_FTP_METHOD_EPRT]      = g_vfs_ftp_task_setup_data_connection_eprt,
+    [G_VFS_FTP_METHOD_PORT]      = g_vfs_ftp_task_setup_data_connection_port
   };
   GVfsFtpMethod method, result;
 



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