changeset 48:e5f6054590b5

2002-11-5 Brian Masney <masneyb@gftp.org> * lib/*.c src/gtk/*.c - removed function declarations for the static functions from the top of the file. I had to rearrange the order of a bunch of functions to avoid compiler warnings * lib/gftp.h - include sys/sysmacros.h. If major() and minor() isn't defined, give a compiler warning and define our own * lib/local.c (local_get_next_file) - if this file is a device, store the major/minor number in the file size * src/gtk/misc-gtk.c (add_file_listbox) - if this file is a device, use the major() and minor() macros to display the major and minor number
author masneyb
date Wed, 06 Nov 2002 02:20:25 +0000
parents eec25f215772
children 0fec02fb9e54
files lib/bookmark.c lib/gftp.h lib/local.c lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/ssh.c lib/sshv2.c src/gtk/bookmarks.c src/gtk/chmod_dialog.c src/gtk/delete_dialog.c src/gtk/dnd.c src/gtk/gftp-gtk.c src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/options_dialog.c src/gtk/transfer.c src/gtk/view_dialog.c
diffstat 18 files changed, 4733 insertions(+), 5142 deletions(-) [+]
line wrap: on
line diff
--- a/lib/bookmark.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/bookmark.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,47 +20,6 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
-static int bookmark_parse_url 			( gftp_request * request, 
-						  const char * url );
-
-void
-bookmark_init (gftp_request * request)
-{
-  g_return_if_fail (request != NULL);
-
-  request->protonum = GFTP_BOOKMARK_NUM;
-  request->init = bookmark_init;
-  request->destroy = NULL;
-  request->connect = NULL;
-  request->disconnect = NULL;
-  request->get_file = NULL;
-  request->put_file = NULL;
-  request->transfer_file = NULL;
-  request->get_next_file_chunk = NULL;
-  request->put_next_file_chunk = NULL;
-  request->end_transfer = NULL;
-  request->list_files = NULL;
-  request->get_next_file = NULL;
-  request->set_data_type = NULL;
-  request->get_file_size = NULL;
-  request->chdir = NULL;
-  request->rmdir = NULL;
-  request->rmfile = NULL;
-  request->mkdir = NULL;
-  request->rename = NULL;
-  request->chmod = NULL;
-  request->set_file_time = NULL;
-  request->site = NULL;
-  request->parse_url = bookmark_parse_url;
-  request->url_prefix = "bookmark";
-  request->protocol_name = "Bookmark";
-  request->need_hostport = 0;
-  request->need_userpass = 0;
-  request->use_threads = 0;
-  request->use_cache = 0;
-  request->always_connected = 0;
-  gftp_set_config_options (request);
-}
 
 static int
 bookmark_parse_url (gftp_request * request, const char * url)
@@ -118,3 +77,43 @@
   return (0);
 }
 
+
+void
+bookmark_init (gftp_request * request)
+{
+  g_return_if_fail (request != NULL);
+
+  request->protonum = GFTP_BOOKMARK_NUM;
+  request->init = bookmark_init;
+  request->destroy = NULL;
+  request->connect = NULL;
+  request->disconnect = NULL;
+  request->get_file = NULL;
+  request->put_file = NULL;
+  request->transfer_file = NULL;
+  request->get_next_file_chunk = NULL;
+  request->put_next_file_chunk = NULL;
+  request->end_transfer = NULL;
+  request->list_files = NULL;
+  request->get_next_file = NULL;
+  request->set_data_type = NULL;
+  request->get_file_size = NULL;
+  request->chdir = NULL;
+  request->rmdir = NULL;
+  request->rmfile = NULL;
+  request->mkdir = NULL;
+  request->rename = NULL;
+  request->chmod = NULL;
+  request->set_file_time = NULL;
+  request->site = NULL;
+  request->parse_url = bookmark_parse_url;
+  request->url_prefix = "bookmark";
+  request->protocol_name = "Bookmark";
+  request->need_hostport = 0;
+  request->need_userpass = 0;
+  request->use_threads = 0;
+  request->use_cache = 0;
+  request->always_connected = 0;
+  gftp_set_config_options (request);
+}
+
--- a/lib/gftp.h	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/gftp.h	Wed Nov 06 02:20:25 2002 +0000
@@ -35,6 +35,7 @@
 #endif
 #include <sys/wait.h>
 #include <sys/utsname.h>
+#include <sys/sysmacros.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <glib.h>
@@ -76,6 +77,18 @@
 #define AF_LOCAL AF_UNIX
 #endif
 
+/* We need the major() and minor() macros in the user interface. If they aren't
+   defined by the system, we'll just define them here. */
+#ifndef major
+#warning major macro was not defined by the system. Defining one that is probably wrong for your system
+#define major(dev) (((dev) >> 8) & 0xff)
+#endif
+
+#ifndef minor
+#warning minor macro was not defined by the system. Defining one that is probably wrong for your system
+#define minor(dev) ((dev) & 0xff)
+#endif
+
 #ifdef HAVE_DMALLOC
 #include <dmalloc.h>
 #endif
--- a/lib/local.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/local.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,51 +20,6 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
-static void local_destroy 			( gftp_request * request );
-static void local_remove_key 			( gpointer key, 
-						  gpointer value, 
-						  gpointer user_data );
-static int local_connect 			( gftp_request * request );
-static void local_disconnect 			( gftp_request * request );
-static long local_get_file 			( gftp_request * request, 
-						  const char *filename,
-						  FILE * fd,
-						  off_t startsize );
-static int local_put_file 			( gftp_request * request, 
-						  const char *filename,
-						  FILE * fd,
-						  off_t startsize,
-						  off_t totalsize );
-static int local_end_transfer 			( gftp_request * request );
-static int local_get_next_file 			( gftp_request * request, 
-						  gftp_file * fle, 
-						  FILE * fd );
-static int local_list_files 			( gftp_request * request );
-static off_t local_get_file_size 		( gftp_request * request,
-						  const char *filename );
-static int local_chdir 				( gftp_request * request, 
-						  const char *directory );
-static int local_rmdir 				( gftp_request * request, 
-						  const char *directory );
-static int local_rmfile 			( gftp_request * request, 
-						  const char *file );
-static int local_mkdir 				( gftp_request * request, 
-						  const char *directory );
-static int local_rename 			( gftp_request * request, 
-						  const char *oldname,
-						  const char *newname );
-static int local_chmod 				( gftp_request * request, 
-						  const char *file, 
-						  int mode );
-static int local_set_file_time 			( gftp_request * request, 
-						  const char *file,
-						  time_t datetime );
-static char *make_text_mode			( gftp_file * fle,
-						  mode_t mode );
-static gint hash_compare 			( gconstpointer path1, 
-						  gconstpointer path2 );
-static guint hash_function 			( gconstpointer key );
-
 typedef struct local_protocol_data_tag
 {
   DIR *dir;
@@ -72,51 +27,10 @@
 } local_protocol_data;
 
 
-void
-local_init (gftp_request * request)
+static void
+local_remove_key (gpointer key, gpointer value, gpointer user_data)
 {
-  local_protocol_data *lpd;
-
-  g_return_if_fail (request != NULL);
-
-  request->protonum = GFTP_LOCAL_NUM;
-  request->init = local_init;
-  request->destroy = local_destroy;
-  request->connect = local_connect;
-  request->disconnect = local_disconnect;
-  request->get_file = local_get_file;
-  request->put_file = local_put_file;
-  request->transfer_file = NULL;
-  request->get_next_file_chunk = NULL;
-  request->put_next_file_chunk = NULL;
-  request->end_transfer = local_end_transfer;
-  request->abort_transfer = local_end_transfer; /* NOTE: uses end_transfer */
-  request->list_files = local_list_files;
-  request->get_next_file = local_get_next_file;
-  request->set_data_type = NULL;
-  request->get_file_size = local_get_file_size;
-  request->chdir = local_chdir;
-  request->rmdir = local_rmdir;
-  request->rmfile = local_rmfile;
-  request->mkdir = local_mkdir;
-  request->rename = local_rename;
-  request->chmod = local_chmod;
-  request->set_file_time = local_set_file_time;
-  request->site = NULL;
-  request->parse_url = NULL;
-  request->url_prefix = "file";
-  request->protocol_name = "Local";
-  request->need_hostport = 0;
-  request->need_userpass = 0;
-  request->use_cache = 0;
-  request->use_threads = 0;
-  request->always_connected = 1;
-  gftp_set_config_options (request);
-
-  lpd = g_malloc0 (sizeof (*lpd));
-  request->protocol_data = lpd;
-  lpd->userhash = g_hash_table_new (hash_function, hash_compare);
-  lpd->grouphash = g_hash_table_new (hash_function, hash_compare);
+  g_free (value);
 }
 
 
@@ -137,13 +51,6 @@
 }
 
 
-static void
-local_remove_key (gpointer key, gpointer value, gpointer user_data)
-{
-  g_free (value);
-}
-
-
 static int
 local_connect (gftp_request * request)
 {
@@ -357,6 +264,92 @@
 }
 
 
+static char *
+make_text_mode (gftp_file * fle, mode_t mode)
+{
+  char *str;
+
+  str = g_malloc0 (11);
+  
+  str[0] = '?';
+  if (S_ISREG (mode))
+    str[0] = '-';
+
+  if (S_ISLNK (mode))
+    {
+      fle->islink = 1; 
+      str[0] = 'l';
+    }
+
+  if (S_ISBLK (mode))
+     {
+       fle->isblock = 1;
+       str[0] = 'b';
+     }
+
+  if (S_ISCHR (mode))
+     {
+       fle->ischar = 1;
+       str[0] = 'c';
+    }
+
+  if (S_ISFIFO (mode))
+    {
+      fle->isfifo = 1;
+      str[0] = 'p';
+    }
+
+  if (S_ISSOCK (mode))
+    {
+      fle->issocket = 1;
+      str[0] = 's';
+    }
+
+  if (S_ISDIR (mode))
+    {
+      fle->isdir = 1;
+      str[0] = 'd';
+    }
+
+  str[1] = mode & S_IRUSR ? 'r' : '-';
+  str[2] = mode & S_IWUSR ? 'w' : '-';
+
+  if ((mode & S_ISUID) && (mode & S_IXUSR))
+    str[3] = 's';
+  else if (mode & S_ISUID)
+    str[3] = 'S';
+  else if (mode & S_IXUSR)
+    str[3] = 'x';
+  else
+    str[3] = '-';
+    
+  str[4] = mode & S_IRGRP ? 'r' : '-';
+  str[5] = mode & S_IWGRP ? 'w' : '-';
+
+  if ((mode & S_ISGID) && (mode & S_IXGRP))
+    str[6] = 's';
+  else if (mode & S_ISGID)
+    str[6] = 'S';
+  else if (mode & S_IXGRP)
+    str[6] = 'x';
+  else
+    str[6] = '-';
+
+  str[7] = mode & S_IROTH ? 'r' : '-';
+  str[8] = mode & S_IWOTH ? 'w' : '-';
+
+  if ((mode & S_ISVTX) && (mode & S_IXOTH))
+    str[9] = 't';
+  else if (mode & S_ISVTX)
+    str[9] = 'T';
+  else if (mode & S_IXOTH)
+    str[9] = 'x';
+  else
+    str[9] = '-';
+  return (str);
+}
+
+
 static int
 local_get_next_file (gftp_request * request, gftp_file * fle, FILE * fd)
 {
@@ -440,14 +433,7 @@
 
   if ((fle->attribs[0] == 'b' || fle->attribs[0] == 'u' ||
        fle->attribs[0] == 'c'))
-    {
-      /* FIXME find out if sys/sysmacros.h is portable, and if 
-         #define {major,minor} is portable. If so, use that instead. If not,
-         I will have to add a configure flag to find out the size of the
-         major numbers */
-      fle->size = ((((int) st.st_rdev) >> 8) & 0xFF) << 16;
-      fle->size |= st.st_rdev & 0xFF;
-    }
+    fle->size = (off_t) st.st_rdev;
   else
     fle->size = st.st_size;
 
@@ -684,92 +670,6 @@
 }
 
 
-static char *
-make_text_mode (gftp_file * fle, mode_t mode)
-{
-  char *str;
-
-  str = g_malloc0 (11);
-  
-  str[0] = '?';
-  if (S_ISREG (mode))
-    str[0] = '-';
-
-  if (S_ISLNK (mode))
-    {
-      fle->islink = 1; 
-      str[0] = 'l';
-    }
-
-  if (S_ISBLK (mode))
-     {
-       fle->isblock = 1;
-       str[0] = 'b';
-     }
-
-  if (S_ISCHR (mode))
-     {
-       fle->ischar = 1;
-       str[0] = 'c';
-    }
-
-  if (S_ISFIFO (mode))
-    {
-      fle->isfifo = 1;
-      str[0] = 'p';
-    }
-
-  if (S_ISSOCK (mode))
-    {
-      fle->issocket = 1;
-      str[0] = 's';
-    }
-
-  if (S_ISDIR (mode))
-    {
-      fle->isdir = 1;
-      str[0] = 'd';
-    }
-
-  str[1] = mode & S_IRUSR ? 'r' : '-';
-  str[2] = mode & S_IWUSR ? 'w' : '-';
-
-  if ((mode & S_ISUID) && (mode & S_IXUSR))
-    str[3] = 's';
-  else if (mode & S_ISUID)
-    str[3] = 'S';
-  else if (mode & S_IXUSR)
-    str[3] = 'x';
-  else
-    str[3] = '-';
-    
-  str[4] = mode & S_IRGRP ? 'r' : '-';
-  str[5] = mode & S_IWGRP ? 'w' : '-';
-
-  if ((mode & S_ISGID) && (mode & S_IXGRP))
-    str[6] = 's';
-  else if (mode & S_ISGID)
-    str[6] = 'S';
-  else if (mode & S_IXGRP)
-    str[6] = 'x';
-  else
-    str[6] = '-';
-
-  str[7] = mode & S_IROTH ? 'r' : '-';
-  str[8] = mode & S_IWOTH ? 'w' : '-';
-
-  if ((mode & S_ISVTX) && (mode & S_IXOTH))
-    str[9] = 't';
-  else if (mode & S_ISVTX)
-    str[9] = 'T';
-  else if (mode & S_IXOTH)
-    str[9] = 'x';
-  else
-    str[9] = '-';
-  return (str);
-}
-
-
 static gint
 hash_compare (gconstpointer path1, gconstpointer path2)
 {
@@ -783,3 +683,51 @@
   return (GPOINTER_TO_UINT (key));
 }
 
+
+void
+local_init (gftp_request * request)
+{
+  local_protocol_data *lpd;
+
+  g_return_if_fail (request != NULL);
+
+  request->protonum = GFTP_LOCAL_NUM;
+  request->init = local_init;
+  request->destroy = local_destroy;
+  request->connect = local_connect;
+  request->disconnect = local_disconnect;
+  request->get_file = local_get_file;
+  request->put_file = local_put_file;
+  request->transfer_file = NULL;
+  request->get_next_file_chunk = NULL;
+  request->put_next_file_chunk = NULL;
+  request->end_transfer = local_end_transfer;
+  request->abort_transfer = local_end_transfer; /* NOTE: uses end_transfer */
+  request->list_files = local_list_files;
+  request->get_next_file = local_get_next_file;
+  request->set_data_type = NULL;
+  request->get_file_size = local_get_file_size;
+  request->chdir = local_chdir;
+  request->rmdir = local_rmdir;
+  request->rmfile = local_rmfile;
+  request->mkdir = local_mkdir;
+  request->rename = local_rename;
+  request->chmod = local_chmod;
+  request->set_file_time = local_set_file_time;
+  request->site = NULL;
+  request->parse_url = NULL;
+  request->url_prefix = "file";
+  request->protocol_name = "Local";
+  request->need_hostport = 0;
+  request->need_userpass = 0;
+  request->use_cache = 0;
+  request->use_threads = 0;
+  request->always_connected = 1;
+  gftp_set_config_options (request);
+
+  lpd = g_malloc0 (sizeof (*lpd));
+  request->protocol_data = lpd;
+  lpd->userhash = g_hash_table_new (hash_function, hash_compare);
+  lpd->grouphash = g_hash_table_new (hash_function, hash_compare);
+}
+
--- a/lib/protocols.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/protocols.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,27 +20,6 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
-static time_t parse_time 			( char **str );
-static int gftp_parse_ls_eplf 			( char *str, 
-						  gftp_file * fle );
-static int gftp_parse_ls_unix 			( char *str, 
-						  int cols, 
-						  gftp_file * fle );
-static int gftp_parse_ls_nt 			( char *str, 
-						  gftp_file * fle );
-static int gftp_parse_ls_novell 		( char *str, 
-						  gftp_file * fle );
-static char *copy_token 			( char **dest, 
-						  char *source );
-static char *goto_next_token 			( char *pos );
-static GList * gftp_get_dir_listing 		( gftp_transfer * transfer,
-						  int getothdir );
-static GHashTable * gftp_gen_dir_hash 		( gftp_request * request );
-static void gftp_destroy_dir_hash 		( GHashTable * dirhash );
-static void destroy_hash_ent 			( gpointer key, 
-						  gpointer value, 
-						  gpointer user_data );
-
 gftp_request *
 gftp_request_new (void)
 {
@@ -1043,87 +1022,45 @@
 }
 
 
-int
-gftp_parse_ls (const char *lsoutput, gftp_file * fle)
+static char *
+copy_token (char **dest, char *source)
 {
-  int result, cols;
-  char *str, *pos;
-
-  g_return_val_if_fail (lsoutput != NULL, -2);
-  g_return_val_if_fail (fle != NULL, -2);
-
-  str = g_malloc (strlen (lsoutput) + 1);
-  strcpy (str, lsoutput);
-  memset (fle, 0, sizeof (*fle));
+  /* This function is used internally by gftp_parse_ls () */
+  char *endpos, savepos;
 
-  if (str[strlen (str) - 1] == '\n')
-    str[strlen (str) - 1] = '\0';
-  if (str[strlen (str) - 1] == '\r')
-    str[strlen (str) - 1] = '\0';
-  if (*lsoutput == '+') 			/* EPLF format */
-    result = gftp_parse_ls_eplf (str, fle);
-  else if (isdigit ((int) str[0]) && str[2] == '-') 	/* DOS/WinNT format */
-    result = gftp_parse_ls_nt (str, fle);
-  else if (str[1] == ' ' && str[2] == '[') 	/* Novell format */
-    result = gftp_parse_ls_novell (str, fle);
-  else
-    {
-      /* UNIX/MacOS format */
+  endpos = source;
+  while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
+    endpos++;
+  if (*endpos == '\0')
+    return (NULL);
 
-      /* If there is no space between the attribs and links field, just make one */
-      if (strlen (str) > 10)
-	str[10] = ' ';
+  savepos = *endpos;
+  *endpos = '\0';
+  *dest = g_malloc (endpos - source + 1);
+  strcpy (*dest, source);
+  *endpos = savepos;
 
-      /* Determine the number of columns */
-      cols = 0;
-      pos = str;
-      while (*pos != '\0')
-	{
-	  while (*pos != '\0' && *pos != ' ' && *pos != '\t')
-	    {
-	      if (*pos == ':')
-		break;
-	      pos++;
-	    }
+  /* Skip the blanks till we get to the next entry */
+  source = endpos + 1;
+  while ((*source == ' ' || *source == '\t') && *source != '\0')
+    source++;
+  return (source);
+}
 
-	  cols++;
-
-	  if (*pos == ':')
-	    {
-	      cols++;
-	      break;
-	    }
-
-	  while (*pos == ' ' || *pos == '\t')
-	    pos++;
-	}
 
-      if (cols > 6)
-	result = gftp_parse_ls_unix (str, cols, fle);
-      else
-	result = -2;
-    }
-  g_free (str);
-
-  if (fle->attribs == NULL)
-    return (result);
+static char *
+goto_next_token (char *pos)
+{
+  while (*pos != ' ' && *pos != '\t' && *pos != '\0')
+    pos++;
 
-  if (*fle->attribs == 'd')
-    fle->isdir = 1;
-  if (*fle->attribs == 'l')
-    fle->islink = 1;
-  if (strchr (fle->attribs, 'x') != NULL && !fle->isdir && !fle->islink)
-    fle->isexe = 1;
-  if (*fle->attribs == 'b')
-    fle->isblock = 1;
-  if (*fle->attribs == 'c')
-    fle->ischar = 1;
-  if (*fle->attribs == 's')
-    fle->issocket = 1;
-  if (*fle->attribs == 'p')
-    fle->isfifo = 1;
+  if (pos == '\0')
+    return (pos);
 
-  return (result);
+  while ((*pos == ' ' || *pos == '\t') && *pos != '\0')
+    pos++;
+
+  return (pos);
 }
 
 
@@ -1456,45 +1393,138 @@
 }
 
 
-static char *
-copy_token (char **dest, char *source)
+int
+gftp_parse_ls (const char *lsoutput, gftp_file * fle)
 {
-  /* This function is used internally by gftp_parse_ls () */
-  char *endpos, savepos;
+  int result, cols;
+  char *str, *pos;
+
+  g_return_val_if_fail (lsoutput != NULL, -2);
+  g_return_val_if_fail (fle != NULL, -2);
+
+  str = g_malloc (strlen (lsoutput) + 1);
+  strcpy (str, lsoutput);
+  memset (fle, 0, sizeof (*fle));
 
-  endpos = source;
-  while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
-    endpos++;
-  if (*endpos == '\0')
-    return (NULL);
+  if (str[strlen (str) - 1] == '\n')
+    str[strlen (str) - 1] = '\0';
+  if (str[strlen (str) - 1] == '\r')
+    str[strlen (str) - 1] = '\0';
+  if (*lsoutput == '+') 			/* EPLF format */
+    result = gftp_parse_ls_eplf (str, fle);
+  else if (isdigit ((int) str[0]) && str[2] == '-') 	/* DOS/WinNT format */
+    result = gftp_parse_ls_nt (str, fle);
+  else if (str[1] == ' ' && str[2] == '[') 	/* Novell format */
+    result = gftp_parse_ls_novell (str, fle);
+  else
+    {
+      /* UNIX/MacOS format */
+
+      /* If there is no space between the attribs and links field, just make one */
+      if (strlen (str) > 10)
+	str[10] = ' ';
 
-  savepos = *endpos;
-  *endpos = '\0';
-  *dest = g_malloc (endpos - source + 1);
-  strcpy (*dest, source);
-  *endpos = savepos;
+      /* Determine the number of columns */
+      cols = 0;
+      pos = str;
+      while (*pos != '\0')
+	{
+	  while (*pos != '\0' && *pos != ' ' && *pos != '\t')
+	    {
+	      if (*pos == ':')
+		break;
+	      pos++;
+	    }
+
+	  cols++;
+
+	  if (*pos == ':')
+	    {
+	      cols++;
+	      break;
+	    }
+
+	  while (*pos == ' ' || *pos == '\t')
+	    pos++;
+	}
 
-  /* Skip the blanks till we get to the next entry */
-  source = endpos + 1;
-  while ((*source == ' ' || *source == '\t') && *source != '\0')
-    source++;
-  return (source);
+      if (cols > 6)
+	result = gftp_parse_ls_unix (str, cols, fle);
+      else
+	result = -2;
+    }
+  g_free (str);
+
+  if (fle->attribs == NULL)
+    return (result);
+
+  if (*fle->attribs == 'd')
+    fle->isdir = 1;
+  if (*fle->attribs == 'l')
+    fle->islink = 1;
+  if (strchr (fle->attribs, 'x') != NULL && !fle->isdir && !fle->islink)
+    fle->isexe = 1;
+  if (*fle->attribs == 'b')
+    fle->isblock = 1;
+  if (*fle->attribs == 'c')
+    fle->ischar = 1;
+  if (*fle->attribs == 's')
+    fle->issocket = 1;
+  if (*fle->attribs == 'p')
+    fle->isfifo = 1;
+
+  return (result);
 }
 
 
-static char *
-goto_next_token (char *pos)
+static GHashTable *
+gftp_gen_dir_hash (gftp_request * request)
 {
-  while (*pos != ' ' && *pos != '\t' && *pos != '\0')
-    pos++;
+  unsigned long *newsize;
+  GHashTable * dirhash;
+  gftp_file * fle;
+  char * newname;
+
 
-  if (pos == '\0')
-    return (pos);
+  dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
+  if (gftp_list_files (request) == 0)
+    {
+      fle = g_malloc0 (sizeof (*fle));
+      while (gftp_get_next_file (request, NULL, fle) > 0)
+        {
+          newname = fle->file;
+          newsize = g_malloc (sizeof (unsigned long));
+          *newsize = fle->size;
+          g_hash_table_insert (dirhash, newname, newsize);
+          fle->file = NULL;
+          gftp_file_destroy (fle);
+        }
+      gftp_end_transfer (request);
+      g_free (fle);
+    }
+  else
+    {
+      g_hash_table_destroy (dirhash);
+      dirhash = NULL;
+    }
+  return (dirhash);
+}
 
-  while ((*pos == ' ' || *pos == '\t') && *pos != '\0')
-    pos++;
+
+static void
+destroy_hash_ent (gpointer key, gpointer value, gpointer user_data)
+{
 
-  return (pos);
+  g_free (key);
+  g_free (value);
+}
+
+
+static void
+gftp_destroy_dir_hash (GHashTable * dirhash)
+{
+  g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
+  g_hash_table_destroy (dirhash);
 }
 
 
@@ -1663,57 +1693,6 @@
 }
 
 
-static GHashTable *
-gftp_gen_dir_hash (gftp_request * request)
-{
-  unsigned long *newsize;
-  GHashTable * dirhash;
-  gftp_file * fle;
-  char * newname;
-
-
-  dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
-  if (gftp_list_files (request) == 0)
-    {
-      fle = g_malloc0 (sizeof (*fle));
-      while (gftp_get_next_file (request, NULL, fle) > 0)
-        {
-          newname = fle->file;
-          newsize = g_malloc (sizeof (unsigned long));
-          *newsize = fle->size;
-          g_hash_table_insert (dirhash, newname, newsize);
-          fle->file = NULL;
-          gftp_file_destroy (fle);
-        }
-      gftp_end_transfer (request);
-      g_free (fle);
-    }
-  else
-    {
-      g_hash_table_destroy (dirhash);
-      dirhash = NULL;
-    }
-  return (dirhash);
-}
-
-
-static void
-gftp_destroy_dir_hash (GHashTable * dirhash)
-{
-  g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
-  g_hash_table_destroy (dirhash);
-}
-
-
-static void
-destroy_hash_ent (gpointer key, gpointer value, gpointer user_data)
-{
-
-  g_free (key);
-  g_free (value);
-}
-
-
 int
 gftp_get_file_transfer_mode (char *filename, int def)
 {
--- a/lib/rfc2068.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/rfc2068.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,32 +20,6 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
-static int rfc2068_connect 			( gftp_request * request );
-static void rfc2068_disconnect 			( gftp_request * request );
-static long rfc2068_get_file 			( gftp_request * request, 
-						  const char *filename, 
-						  FILE * fd,
-						  off_t startsize );
-static size_t rfc2068_get_next_file_chunk 	( gftp_request * request, 
-						  char *buf, 
-						  size_t size );
-static int rfc2068_end_transfer 		( gftp_request * request );
-static int rfc2068_list_files 			( gftp_request * request );
-static off_t rfc2068_get_file_size 		( gftp_request * request, 
-						  const char *filename );
-static int rfc2068_get_next_file 		( gftp_request * request, 
-						  gftp_file * fle, 
-						  FILE * fd );
-static int rfc2068_chdir 			( gftp_request * request, 
-						  const char *directory );
-static unsigned long rfc2068_send_command 	( gftp_request * request, 
-						  const char *command, 
-						  const char *extrahdr );
-static unsigned long rfc2068_read_response 	( gftp_request * request );
-static int parse_html_line 			( char *tempstr, 
-						  gftp_file * fle );
-static char *base64_encode 			( char *str );
-
 typedef struct rfc2068_params_tag
 {
   unsigned long read_bytes,
@@ -53,43 +27,185 @@
   int chunked_transfer : 1;
 } rfc2068_params;
 
-void
-rfc2068_init (gftp_request * request)
+
+static char *
+base64_encode (char *str)
 {
-  g_return_if_fail (request != NULL);
+
+/* The standard to Base64 encoding can be found in RFC2045 */
+
+  char *newstr, *newpos, *fillpos, *pos;
+  unsigned char table[64], encode[3];
+  int i, num;
+
+  for (i = 0; i < 26; i++)
+    {
+      table[i] = 'A' + i;
+      table[i + 26] = 'a' + i;
+    }
+
+  for (i = 0; i < 10; i++)
+    table[i + 52] = '0' + i;
+
+  table[62] = '+';
+  table[63] = '-';
+
+  num = strlen (str) / 3;
+  if (strlen (str) % 3 > 0)
+    num++;
+  newstr = g_malloc (num * 4 + 1);
+  newstr[num * 4] = '\0';
+  newpos = newstr;
+
+  pos = str;
+  while (*pos != '\0')
+    {
+      memset (encode, 0, sizeof (encode));
+      for (i = 0; i < 3 && *pos != '\0'; i++)
+	encode[i] = *pos++;
+
+      fillpos = newpos;
+      *newpos++ = table[encode[0] >> 2];
+      *newpos++ = table[(encode[0] & 3) << 4 | encode[1] >> 4];
+      *newpos++ = table[(encode[1] & 0xF) << 2 | encode[2] >> 6];
+      *newpos++ = table[encode[2] & 0x3F];
+      while (i < 3)
+	fillpos[++i] = '=';
+    }
+  return (newstr);
+}
+
+
+static unsigned long
+rfc2068_read_response (gftp_request * request)
+{
+  rfc2068_params * params;
+  char tempstr[255];
+
+  params = request->protocol_data;
+  params->max_bytes = 0;
+
+  if (!gftp_fgets (request, tempstr, sizeof (tempstr), request->sockfd))
+    {
+      gftp_disconnect (request);
+      return (0);
+    }
+
+  if (request->last_ftp_response)
+    g_free (request->last_ftp_response);
+  request->last_ftp_response = g_malloc (strlen (tempstr) + 1);
+  strcpy (request->last_ftp_response, tempstr);
+
+  request->logging_function (gftp_logging_recv, request->user_data, "%s",
+                             tempstr);
+
+  params->chunked_transfer = 0;
+  while (1) 
+    {
+      /* Read rest of proxy header */
+      if (!gftp_fgets (request, tempstr, sizeof (tempstr), request->sockfd))
+        {
+          gftp_disconnect (request);
+	  return (0);
+        }
+
+      if (*tempstr == '\r' || *tempstr == '\n')
+        break;
+
+      request->logging_function (gftp_logging_recv, request->user_data, "%s",
+                                 tempstr);
 
-  request->protonum = GFTP_HTTP_NUM;
-  request->init = rfc2068_init;
-  request->destroy = NULL;
-  request->connect = rfc2068_connect;
-  request->disconnect = rfc2068_disconnect;
-  request->get_file = rfc2068_get_file;
-  request->put_file = NULL;
-  request->transfer_file = NULL;
-  request->get_next_file_chunk = rfc2068_get_next_file_chunk;
-  request->put_next_file_chunk = NULL;
-  request->end_transfer = rfc2068_end_transfer;
-  request->abort_transfer = rfc2068_end_transfer; /* NOTE: uses end_transfer */
-  request->list_files = rfc2068_list_files;
-  request->get_next_file = rfc2068_get_next_file;
-  request->set_data_type = NULL;
-  request->get_file_size = rfc2068_get_file_size;
-  request->chdir = rfc2068_chdir;
-  request->rmdir = NULL;
-  request->rmfile = NULL;
-  request->mkdir = NULL;
-  request->rename = NULL;
-  request->chmod = NULL;
-  request->site = NULL;
-  request->url_prefix = "http";
-  request->protocol_name = "HTTP";
-  request->need_hostport = 1;
-  request->need_userpass = 0;
-  request->use_cache = 1;
-  request->use_threads = 1;
-  request->always_connected = 0;
-  request->protocol_data = g_malloc0 (sizeof (rfc2068_params));
-  gftp_set_config_options (request);
+      if (strncmp (tempstr, "Content-Length:", 15) == 0)
+	params->max_bytes = strtol (tempstr + 16, NULL, 10);
+      if (strncmp (tempstr, "Transfer-Encoding: chunked", 26) == 0)
+        params->chunked_transfer = 1;
+    }
+
+  return (params->max_bytes);
+}
+
+
+static unsigned long
+rfc2068_send_command (gftp_request * request, const char *command,
+                      const char *extrahdr)
+{
+  char *tempstr, *str;
+
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
+  g_return_val_if_fail (command != NULL, -2);
+  g_return_val_if_fail (request->sockfd_write != NULL, -2);
+
+  request->logging_function (gftp_logging_send, request->user_data, "%s",
+                             command);
+
+  request->logging_function (gftp_logging_send, request->user_data,
+                             "User-Agent: %s\n", version);
+  fprintf (request->sockfd_write, "%sUser-Agent: %s\nHost: %s\n", command, 
+           version, request->hostname);
+  if (ferror (request->sockfd_write) != 0)
+    {
+      gftp_disconnect (request);
+      return (-2);
+    }
+
+  if (request->use_proxy && request->proxy_username != NULL &&
+      *request->proxy_username != '\0')
+    {
+      tempstr = g_strconcat (request->proxy_username, ":", 
+                             request->proxy_password, NULL);
+      str = base64_encode (tempstr);
+      g_free (tempstr);
+
+      request->logging_function (gftp_logging_send, request->user_data,
+                                 "Proxy-authorization: Basic xxxx:xxxx\n");
+      fprintf (request->sockfd_write, "Proxy-authorization: Basic %s\n", str);
+      g_free (str);
+      if (ferror (request->sockfd_write) != 0)
+        {
+          gftp_disconnect (request);
+	  return (-2);
+        }
+    }
+
+  if (request->username != NULL && *request->username != '\0')
+    {
+      tempstr = g_strconcat (request->username, ":", request->password, NULL);
+      str = base64_encode (tempstr);
+      g_free (tempstr);
+
+      request->logging_function (gftp_logging_send, request->user_data,
+                                 "Authorization: Basic xxxx\n");
+      fprintf (request->sockfd_write, "Authorization: Basic %s\n", str);
+      g_free (str);
+      if (ferror (request->sockfd_write) != 0)
+        {
+          gftp_disconnect (request);
+	  return (-2);
+        }
+    }
+
+  if (extrahdr)
+    {
+      request->logging_function (gftp_logging_send, request->user_data,
+                                 "%s", extrahdr);
+      request->logging_function (gftp_logging_send, request->user_data, "%s",
+                                 extrahdr);
+      fprintf (request->sockfd_write, "%s", extrahdr);
+      if (ferror (request->sockfd_write) != 0)
+        {
+          gftp_disconnect (request);
+          return (-2);
+        }
+    }
+
+  fprintf (request->sockfd_write, "\n");
+  if (ferror (request->sockfd_write) != 0)
+    {
+      gftp_disconnect (request);
+      return (-2);
+    }
+  return (rfc2068_read_response (request));
 }
 
 
@@ -406,223 +522,6 @@
 
 
 static int
-rfc2068_get_next_file (gftp_request * request, gftp_file * fle, FILE * fd)
-{
-  rfc2068_params * params;
-  char tempstr[255];
-  size_t len;
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
-  g_return_val_if_fail (fle != NULL, -2);
-
-  params = request->protocol_data;
-  if (request->last_dir_entry)
-    {
-      g_free (request->last_dir_entry);
-      request->last_dir_entry = NULL;
-    }
-
-  while (1)
-    {
-      if (!gftp_fgets (request, tempstr, sizeof (tempstr), fd))
-        {
-          gftp_file_destroy (fle);
-          return (-2);
-        }
-
-      tempstr[sizeof (tempstr) - 1] = '\0';
-      params->read_bytes += strlen (tempstr);
-
-      if (params->chunked_transfer && strcmp (tempstr, "0\r\n") == 0)
-        {
-          while (gftp_fgets (request, tempstr, sizeof (tempstr), fd))
-            {
-              if (strcmp (tempstr, "\r\n") == 0)
-                break;
-            }
-	  gftp_file_destroy (fle);
-          return (0);
-        }
-
-      if (parse_html_line (tempstr, fle) == 0 || fle->file == NULL)
-	gftp_file_destroy (fle);
-      else
-	break;
-
-      if (params->max_bytes != 0 && params->read_bytes == params->max_bytes)
-	break;
-    }
-
-  if (fle->file == NULL)
-    {
-      gftp_file_destroy (fle);
-      return (-2);
-    }
-
-  len = strlen (tempstr);
-  if (!request->cached)
-    {
-      request->last_dir_entry = g_malloc (len + 1);
-      strcpy (request->last_dir_entry, tempstr);
-      request->last_dir_entry_len = len;
-    }
-  return (feof (fd) ? 0 : len);
-}
-
-
-static int
-rfc2068_chdir (gftp_request * request, const char *directory)
-{
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
-  g_return_val_if_fail (directory != NULL, -2);
-
-  if (request->directory != directory)
-    {
-      if (request->directory)
-        g_free (request->directory);
-      request->directory = g_malloc (strlen (directory) + 1);
-      strcpy (request->directory, directory);
-    }
-  return (0);
-}
-
-
-static unsigned long
-rfc2068_send_command (gftp_request * request, const char *command,
-                      const char *extrahdr)
-{
-  char *tempstr, *str;
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
-  g_return_val_if_fail (command != NULL, -2);
-  g_return_val_if_fail (request->sockfd_write != NULL, -2);
-
-  request->logging_function (gftp_logging_send, request->user_data, "%s",
-                             command);
-
-  request->logging_function (gftp_logging_send, request->user_data,
-                             "User-Agent: %s\n", version);
-  fprintf (request->sockfd_write, "%sUser-Agent: %s\nHost: %s\n", command, 
-           version, request->hostname);
-  if (ferror (request->sockfd_write) != 0)
-    {
-      gftp_disconnect (request);
-      return (-2);
-    }
-
-  if (request->use_proxy && request->proxy_username != NULL &&
-      *request->proxy_username != '\0')
-    {
-      tempstr = g_strconcat (request->proxy_username, ":", 
-                             request->proxy_password, NULL);
-      str = base64_encode (tempstr);
-      g_free (tempstr);
-
-      request->logging_function (gftp_logging_send, request->user_data,
-                                 "Proxy-authorization: Basic xxxx:xxxx\n");
-      fprintf (request->sockfd_write, "Proxy-authorization: Basic %s\n", str);
-      g_free (str);
-      if (ferror (request->sockfd_write) != 0)
-        {
-          gftp_disconnect (request);
-	  return (-2);
-        }
-    }
-
-  if (request->username != NULL && *request->username != '\0')
-    {
-      tempstr = g_strconcat (request->username, ":", request->password, NULL);
-      str = base64_encode (tempstr);
-      g_free (tempstr);
-
-      request->logging_function (gftp_logging_send, request->user_data,
-                                 "Authorization: Basic xxxx\n");
-      fprintf (request->sockfd_write, "Authorization: Basic %s\n", str);
-      g_free (str);
-      if (ferror (request->sockfd_write) != 0)
-        {
-          gftp_disconnect (request);
-	  return (-2);
-        }
-    }
-
-  if (extrahdr)
-    {
-      request->logging_function (gftp_logging_send, request->user_data,
-                                 "%s", extrahdr);
-      request->logging_function (gftp_logging_send, request->user_data, "%s",
-                                 extrahdr);
-      fprintf (request->sockfd_write, "%s", extrahdr);
-      if (ferror (request->sockfd_write) != 0)
-        {
-          gftp_disconnect (request);
-          return (-2);
-        }
-    }
-
-  fprintf (request->sockfd_write, "\n");
-  if (ferror (request->sockfd_write) != 0)
-    {
-      gftp_disconnect (request);
-      return (-2);
-    }
-  return (rfc2068_read_response (request));
-}
-
-
-static unsigned long
-rfc2068_read_response (gftp_request * request)
-{
-  rfc2068_params * params;
-  char tempstr[255];
-
-  params = request->protocol_data;
-  params->max_bytes = 0;
-
-  if (!gftp_fgets (request, tempstr, sizeof (tempstr), request->sockfd))
-    {
-      gftp_disconnect (request);
-      return (0);
-    }
-
-  if (request->last_ftp_response)
-    g_free (request->last_ftp_response);
-  request->last_ftp_response = g_malloc (strlen (tempstr) + 1);
-  strcpy (request->last_ftp_response, tempstr);
-
-  request->logging_function (gftp_logging_recv, request->user_data, "%s",
-                             tempstr);
-
-  params->chunked_transfer = 0;
-  while (1) 
-    {
-      /* Read rest of proxy header */
-      if (!gftp_fgets (request, tempstr, sizeof (tempstr), request->sockfd))
-        {
-          gftp_disconnect (request);
-	  return (0);
-        }
-
-      if (*tempstr == '\r' || *tempstr == '\n')
-        break;
-
-      request->logging_function (gftp_logging_recv, request->user_data, "%s",
-                                 tempstr);
-
-      if (strncmp (tempstr, "Content-Length:", 15) == 0)
-	params->max_bytes = strtol (tempstr + 16, NULL, 10);
-      if (strncmp (tempstr, "Transfer-Encoding: chunked", 26) == 0)
-        params->chunked_transfer = 1;
-    }
-
-  return (params->max_bytes);
-}
-
-
-static int
 parse_html_line (char *tempstr, gftp_file * fle)
 {
   char months[13][3] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
@@ -803,49 +702,126 @@
 }
 
 
-static char *
-base64_encode (char *str)
+static int
+rfc2068_get_next_file (gftp_request * request, gftp_file * fle, FILE * fd)
 {
+  rfc2068_params * params;
+  char tempstr[255];
+  size_t len;
 
-/* The standard to Base64 encoding can be found in RFC2045 */
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
+  g_return_val_if_fail (fle != NULL, -2);
+
+  params = request->protocol_data;
+  if (request->last_dir_entry)
+    {
+      g_free (request->last_dir_entry);
+      request->last_dir_entry = NULL;
+    }
+
+  while (1)
+    {
+      if (!gftp_fgets (request, tempstr, sizeof (tempstr), fd))
+        {
+          gftp_file_destroy (fle);
+          return (-2);
+        }
 
-  char *newstr, *newpos, *fillpos, *pos;
-  unsigned char table[64], encode[3];
-  int i, num;
+      tempstr[sizeof (tempstr) - 1] = '\0';
+      params->read_bytes += strlen (tempstr);
+
+      if (params->chunked_transfer && strcmp (tempstr, "0\r\n") == 0)
+        {
+          while (gftp_fgets (request, tempstr, sizeof (tempstr), fd))
+            {
+              if (strcmp (tempstr, "\r\n") == 0)
+                break;
+            }
+	  gftp_file_destroy (fle);
+          return (0);
+        }
 
-  for (i = 0; i < 26; i++)
+      if (parse_html_line (tempstr, fle) == 0 || fle->file == NULL)
+	gftp_file_destroy (fle);
+      else
+	break;
+
+      if (params->max_bytes != 0 && params->read_bytes == params->max_bytes)
+	break;
+    }
+
+  if (fle->file == NULL)
     {
-      table[i] = 'A' + i;
-      table[i + 26] = 'a' + i;
+      gftp_file_destroy (fle);
+      return (-2);
     }
 
-  for (i = 0; i < 10; i++)
-    table[i + 52] = '0' + i;
+  len = strlen (tempstr);
+  if (!request->cached)
+    {
+      request->last_dir_entry = g_malloc (len + 1);
+      strcpy (request->last_dir_entry, tempstr);
+      request->last_dir_entry_len = len;
+    }
+  return (feof (fd) ? 0 : len);
+}
 
-  table[62] = '+';
-  table[63] = '-';
 
-  num = strlen (str) / 3;
-  if (strlen (str) % 3 > 0)
-    num++;
-  newstr = g_malloc (num * 4 + 1);
-  newstr[num * 4] = '\0';
-  newpos = newstr;
+static int
+rfc2068_chdir (gftp_request * request, const char *directory)
+{
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
+  g_return_val_if_fail (directory != NULL, -2);
+
+  if (request->directory != directory)
+    {
+      if (request->directory)
+        g_free (request->directory);
+      request->directory = g_malloc (strlen (directory) + 1);
+      strcpy (request->directory, directory);
+    }
+  return (0);
+}
+
+
+void
+rfc2068_init (gftp_request * request)
+{
+  g_return_if_fail (request != NULL);
 
-  pos = str;
-  while (*pos != '\0')
-    {
-      memset (encode, 0, sizeof (encode));
-      for (i = 0; i < 3 && *pos != '\0'; i++)
-	encode[i] = *pos++;
+  request->protonum = GFTP_HTTP_NUM;
+  request->init = rfc2068_init;
+  request->destroy = NULL;
+  request->connect = rfc2068_connect;
+  request->disconnect = rfc2068_disconnect;
+  request->get_file = rfc2068_get_file;
+  request->put_file = NULL;
+  request->transfer_file = NULL;
+  request->get_next_file_chunk = rfc2068_get_next_file_chunk;
+  request->put_next_file_chunk = NULL;
+  request->end_transfer = rfc2068_end_transfer;
+  request->abort_transfer = rfc2068_end_transfer; /* NOTE: uses end_transfer */
+  request->list_files = rfc2068_list_files;
+  request->get_next_file = rfc2068_get_next_file;
+  request->set_data_type = NULL;
+  request->get_file_size = rfc2068_get_file_size;
+  request->chdir = rfc2068_chdir;
+  request->rmdir = NULL;
+  request->rmfile = NULL;
+  request->mkdir = NULL;
+  request->rename = NULL;
+  request->chmod = NULL;
+  request->site = NULL;
+  request->url_prefix = "http";
+  request->protocol_name = "HTTP";
+  request->need_hostport = 1;
+  request->need_userpass = 0;
+  request->use_cache = 1;
+  request->use_threads = 1;
+  request->always_connected = 0;
+  request->protocol_data = g_malloc0 (sizeof (rfc2068_params));
+  gftp_set_config_options (request);
+}
 
-      fillpos = newpos;
-      *newpos++ = table[encode[0] >> 2];
-      *newpos++ = table[(encode[0] & 3) << 4 | encode[1] >> 4];
-      *newpos++ = table[(encode[1] & 0xF) << 2 | encode[2] >> 6];
-      *newpos++ = table[encode[2] & 0x3F];
-      while (i < 3)
-	fillpos[++i] = '=';
-    }
-  return (newstr);
-}
--- a/lib/rfc959.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/rfc959.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,91 +20,243 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
-static int rfc959_connect 			( gftp_request * request );
-static void rfc959_disconnect 			( gftp_request * request );
-static long rfc959_get_file 			( gftp_request * request, 
-						  const char *filename,
-						  FILE * fd,
-						  off_t startsize );
-static int rfc959_put_file 			( gftp_request * request, 
-						  const char *filename,
-						  FILE * fd,
-						  off_t startsize,
-						  off_t totalsize );
-static long rfc959_transfer_file 		( gftp_request *fromreq, 
-						  const char *fromfile, 
-						  off_t fromsize, 
-						  gftp_request *toreq, 
-						  const char *tofile, 
-						  off_t tosize );
-static int rfc959_end_transfer 			( gftp_request * request );
-static int rfc959_abort_transfer 		( gftp_request * request );
-static int rfc959_list_files 			( gftp_request * request );
-static int rfc959_set_data_type 		( gftp_request * request, 
-						  int data_type );
-static off_t rfc959_get_file_size 		( gftp_request * request, 
-						  const char *filename );
-static int rfc959_data_connection_new 		( gftp_request * request );
-static int rfc959_accept_active_connection 	( gftp_request * request );
-static int rfc959_send_command 			( gftp_request * request, 
-						  const char *command );
-static int rfc959_read_response 		( gftp_request * request );
-static int rfc959_chdir 			( gftp_request * request, 
-						  const char *directory );
-static int rfc959_rmdir 			( gftp_request * request, 
-						  const char *directory );
-static int rfc959_rmfile 			( gftp_request * request, 
-						  const char *file );
-static int rfc959_mkdir 			( gftp_request * request, 
-						  const char *directory );
-static int rfc959_rename 			( gftp_request * request, 
-						  const char *oldname, 
-						  const char *newname );
-static int rfc959_chmod 			( gftp_request * request, 
-						  const char *file, 
-						  int mode );
-static int rfc959_site 				( gftp_request * request, 
-						  const char *command );
-static char *parse_ftp_proxy_string 		( gftp_request * request );
+static int
+rfc959_read_response (gftp_request * request)
+{
+  char tempstr[255], code[4];
+
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
+  g_return_val_if_fail (request->sockfd != NULL, -2);
+
+  *code = '\0';
+  if (request->last_ftp_response)
+    {
+      g_free (request->last_ftp_response);
+      request->last_ftp_response = NULL;
+    }
+
+  do
+    {
+      if (!gftp_fgets (request, tempstr, sizeof (tempstr), request->sockfd))
+	break;
+      tempstr[strlen (tempstr) - 1] = '\0';
+      if (tempstr[strlen (tempstr) - 1] == '\r')
+	tempstr[strlen (tempstr) - 1] = '\0';
+      if (isdigit ((int) *tempstr) && isdigit ((int) *(tempstr + 1))
+	  && isdigit ((int) *(tempstr + 2)))
+	{
+	  strncpy (code, tempstr, 3);
+	  code[3] = ' ';
+	}
+      request->logging_function (gftp_logging_recv, request->user_data,
+				 "%s\n", tempstr);
+    }
+  while (strncmp (code, tempstr, 4) != 0);
+
+  if (ferror (request->sockfd)) 
+    {
+      request->logging_function (gftp_logging_send, request->user_data,
+                                 "Error reading from socket: %s\n",
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (-1);
+    }
+
+  request->last_ftp_response = g_malloc (strlen (tempstr) + 1);
+  strcpy (request->last_ftp_response, tempstr);
+
+  if (request->last_ftp_response[0] == '4' &&
+      request->last_ftp_response[1] == '2')
+    gftp_disconnect (request);
+
+  return (*request->last_ftp_response);
+}
+
+
+static int
+rfc959_send_command (gftp_request * request, const char *command)
+{
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
+  g_return_val_if_fail (command != NULL, -2);
+  g_return_val_if_fail (request->sockfd != NULL, -2);
+
+  if (strncmp (command, "PASS", 4) == 0)
+    {
+      request->logging_function (gftp_logging_send, request->user_data, 
+                                 "PASS xxxx\n");
+    }
+  else if (strncmp (command, "ACCT", 4) == 0)
+    {
+      request->logging_function (gftp_logging_send, request->user_data, 
+                                 "ACCT xxxx\n");
+    }
+  else
+    {
+      request->logging_function (gftp_logging_send, request->user_data, "%s",
+                                 command);
+    }
+
+  if (gftp_fwrite (request, command, strlen (command), 
+                   request->sockfd_write) < 0)
+    return (-1);
+
+  return (rfc959_read_response (request));
+}
+
+
+static char *
+parse_ftp_proxy_string (gftp_request * request)
+{
+  char *startpos, *endpos, *oldstr, *newstr, *newval, *tempport;
+
+  g_return_val_if_fail (request != NULL, NULL);
+  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, NULL);
 
-void
-rfc959_init (gftp_request * request)
-{
-  g_return_if_fail (request != NULL);
+  newstr = g_malloc (1);
+  *newstr = '\0';
+  startpos = endpos = request->proxy_config;
+  while (*endpos != '\0')
+    {
+      tempport = NULL;
+      if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'p')
+	{
+	  switch (tolower ((int) *(endpos + 2)))
+	    {
+	    case 'u':
+	      newval = request->proxy_username;
+	      break;
+	    case 'p':
+	      newval = request->proxy_password;
+	      break;
+	    case 'h':
+	      newval = request->proxy_hostname;
+	      break;
+	    case 'o':
+	      tempport = g_strdup_printf ("%d", request->proxy_port);
+	      newval = tempport;
+	      break;
+	    case 'a':
+	      newval = request->proxy_account;
+	      break;
+	    default:
+	      endpos++;
+	      continue;
+	    }
+	}
+      else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'h')
+	{
+	  switch (tolower ((int) *(endpos + 2)))
+	    {
+	    case 'u':
+	      newval = request->username;
+	      break;
+	    case 'p':
+	      newval = request->password;
+	      break;
+	    case 'h':
+	      newval = request->hostname;
+	      break;
+	    case 'o':
+	      tempport = g_strdup_printf ("%d", request->port);
+	      newval = tempport;
+	      break;
+	    case 'a':
+	      newval = request->account;
+	      break;
+	    default:
+	      endpos++;
+	      continue;
+	    }
+	}
+      else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'n')
+	{
+	  *endpos = '\0';
+	  oldstr = newstr;
+	  newstr = g_strconcat (oldstr, startpos, "\r\n", NULL);
+	  g_free (oldstr);
+	  endpos += 2;
+	  startpos = endpos;
+	  continue;
+	}
+      else
+	{
+	  endpos++;
+	  continue;
+	}
 
-  request->protonum = GFTP_FTP_NUM;
-  request->init = rfc959_init;
-  request->destroy = NULL; 
-  request->connect = rfc959_connect;
-  request->disconnect = rfc959_disconnect;
-  request->get_file = rfc959_get_file;
-  request->put_file = rfc959_put_file;
-  request->transfer_file = rfc959_transfer_file;
-  request->get_next_file_chunk = NULL;
-  request->put_next_file_chunk = NULL;
-  request->end_transfer = rfc959_end_transfer;
-  request->abort_transfer = rfc959_abort_transfer;
-  request->list_files = rfc959_list_files;
-  request->get_next_file = rfc959_get_next_file;
-  request->set_data_type = rfc959_set_data_type;
-  request->get_file_size = rfc959_get_file_size;
-  request->chdir = rfc959_chdir;
-  request->rmdir = rfc959_rmdir;
-  request->rmfile = rfc959_rmfile;
-  request->mkdir = rfc959_mkdir;
-  request->rename = rfc959_rename;
-  request->chmod = rfc959_chmod;
-  request->set_file_time = NULL;
-  request->site = rfc959_site;
-  request->parse_url = NULL;
-  request->url_prefix = "ftp";
-  request->protocol_name = "FTP";
-  request->need_hostport = 1;
-  request->need_userpass = 1;
-  request->use_cache = 1;
-  request->use_threads = 1;
-  request->always_connected = 0;
-  gftp_set_config_options (request);
+      *endpos = '\0';
+      oldstr = newstr;
+      if (!newval)
+	newstr = g_strconcat (oldstr, startpos, NULL);
+      else
+	newstr = g_strconcat (oldstr, startpos, newval, NULL);
+      if (tempport)
+	{
+	  g_free (tempport);
+	  tempport = NULL;
+	}
+      g_free (oldstr);
+      endpos += 3;
+      startpos = endpos;
+    }
+  return (newstr);
+}
+
+
+static int
+rfc959_chdir (gftp_request * request, const char *directory)
+{
+  char ret, *tempstr, *dir;
+
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
+  g_return_val_if_fail (directory != NULL, -2);
+
+  if (strcmp (directory, "..") == 0)
+    ret = rfc959_send_command (request, "CDUP\r\n");
+  else
+    {
+      tempstr = g_strconcat ("CWD ", directory, "\r\n", NULL);
+      ret = rfc959_send_command (request, tempstr);
+      g_free (tempstr);
+    }
+
+  if (ret != '2')
+    return (-2);
+
+  if (directory != request->directory)
+    {
+      if (request->directory)
+        {
+          g_free (request->directory);
+          request->directory = NULL;
+        }
+
+      if (rfc959_send_command (request, "PWD\r\n") != '2')
+        return (-2);
+
+      tempstr = strchr (request->last_ftp_response, '"');
+      if (tempstr != NULL)
+        dir = tempstr + 1;
+      else
+        return (-2);
+
+      tempstr = strchr (dir, '"');
+      if (tempstr != NULL)
+        *tempstr = '\0';
+      else
+        {
+          gftp_disconnect (request);
+          return (-2);
+        }
+
+      request->directory = g_malloc (strlen (dir) + 1);
+      strcpy (request->directory, dir);
+    }
+
+  return (0);
 }
 
 
@@ -286,6 +438,166 @@
 }
 
 
+static int
+rfc959_data_connection_new (gftp_request * request)
+{
+  char *pos, *pos1, resp, *command;
+  struct sockaddr_in data_addr;
+  size_t data_addr_len;
+  unsigned int temp[6];
+  unsigned char ad[6];
+  int i, sock;
+
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
+  g_return_val_if_fail (request->sockfd != NULL, -2);
+
+  if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+				 _("Failed to create a socket: %s\n"),
+				 g_strerror (errno));
+      gftp_disconnect (request);
+      return (-1);
+    }
+
+  data_addr_len = sizeof (data_addr);
+  memset (&data_addr, 0, data_addr_len);
+  data_addr.sin_family = AF_INET;
+
+  if (request->transfer_type == gftp_transfer_passive)
+    {
+      if ((resp = rfc959_send_command (request, "PASV\r\n")) != '2')
+	{
+          if (request->sockfd == NULL)
+            return (-2);
+
+	  request->transfer_type = gftp_transfer_active;
+	  return (rfc959_data_connection_new (request));
+	}
+      pos = request->last_ftp_response + 4;
+      while (!isdigit ((int) *pos) && *pos != '\0')
+        pos++;
+      if (*pos == '\0')
+        {
+          gftp_disconnect (request);
+          close (sock);
+          return (-2);
+        }
+      if (sscanf (pos, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
+                  &temp[3], &temp[4], &temp[5]) != 6)
+        {
+          gftp_disconnect (request);
+          close (sock);
+          return (-2);
+        }
+      for (i = 0; i < 6; i++)
+        ad[i] = (unsigned char) (temp[i] & 0xff);
+
+      memcpy (&data_addr.sin_addr, &ad[0], 4);
+      memcpy (&data_addr.sin_port, &ad[4], 2);
+      if (connect (sock, (struct sockaddr *) &data_addr, data_addr_len) == -1)
+        {
+          request->logging_function (gftp_logging_error, request->user_data,
+                                    _("Cannot create a data connection: %s\n"),
+                                    g_strerror (errno));
+          gftp_disconnect (request);
+          close (sock);
+          return (-1);
+	}
+    }
+  else
+    {
+      getsockname (fileno (request->sockfd), (struct sockaddr *) &data_addr,
+		   &data_addr_len);
+      data_addr.sin_port = 0;
+      if (bind (sock, (struct sockaddr *) &data_addr, data_addr_len) == -1)
+	{
+	  request->logging_function (gftp_logging_error, request->user_data,
+				     _("Cannot bind a port: %s\n"),
+				     g_strerror (errno));
+          gftp_disconnect (request);
+	  close (sock);
+	  return (-1);
+	}
+
+      getsockname (sock, (struct sockaddr *) &data_addr, &data_addr_len);
+      if (listen (sock, 1) == -1)
+	{
+	  request->logging_function (gftp_logging_error, request->user_data,
+				     _("Cannot listen on port %d: %s\n"),
+				     ntohs (data_addr.sin_port),
+				     g_strerror (errno));
+          gftp_disconnect (request);
+	  close (sock);
+	  return (-1);
+	}
+      pos = (char *) &data_addr.sin_addr;
+      pos1 = (char *) &data_addr.sin_port;
+      command = g_strdup_printf ("PORT %u,%u,%u,%u,%u,%u\r\n",
+				 pos[0] & 0xff, pos[1] & 0xff, pos[2] & 0xff,
+				 pos[3] & 0xff, pos1[0] & 0xff,
+				 pos1[1] & 0xff);
+      resp = rfc959_send_command (request, command);
+      g_free (command);
+      if (resp != '2')
+	{
+          gftp_disconnect (request);
+	  close (sock);
+	  return (-2);
+	}
+    }
+
+  if ((request->datafd = fdopen (sock, "rb+")) == NULL)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Cannot fdopen() socket: %s\n"),
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (-2);
+    }
+
+  return (0);
+}
+
+
+static int
+rfc959_accept_active_connection (gftp_request * request)
+{
+  struct sockaddr_in cli_addr;
+  size_t cli_addr_len;
+  int infd;
+
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
+  g_return_val_if_fail (request->datafd != NULL, -2);
+  g_return_val_if_fail (request->transfer_type == gftp_transfer_active, -2);
+
+  cli_addr_len = sizeof (cli_addr);
+  if ((infd = accept (fileno (request->datafd), (struct sockaddr *) &cli_addr,
+       &cli_addr_len)) == -1)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                _("Cannot accept connection from server: %s\n"),
+                                g_strerror (errno));
+      gftp_disconnect (request);
+      return (-1);
+    }
+
+  fclose (request->datafd);
+
+  if ((request->datafd = fdopen (infd, "rb+")) == NULL)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Cannot fdopen() socket: %s\n"),
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (-2);
+    }
+  return (0);
+}
+
+
 static long
 rfc959_get_file (gftp_request * request, const char *filename, FILE * fd,
                  off_t startsize)
@@ -659,307 +971,6 @@
 
 
 static int
-rfc959_data_connection_new (gftp_request * request)
-{
-  char *pos, *pos1, resp, *command;
-  struct sockaddr_in data_addr;
-  size_t data_addr_len;
-  unsigned int temp[6];
-  unsigned char ad[6];
-  int i, sock;
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
-  g_return_val_if_fail (request->sockfd != NULL, -2);
-
-  if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-				 _("Failed to create a socket: %s\n"),
-				 g_strerror (errno));
-      gftp_disconnect (request);
-      return (-1);
-    }
-
-  data_addr_len = sizeof (data_addr);
-  memset (&data_addr, 0, data_addr_len);
-  data_addr.sin_family = AF_INET;
-
-  if (request->transfer_type == gftp_transfer_passive)
-    {
-      if ((resp = rfc959_send_command (request, "PASV\r\n")) != '2')
-	{
-          if (request->sockfd == NULL)
-            return (-2);
-
-	  request->transfer_type = gftp_transfer_active;
-	  return (rfc959_data_connection_new (request));
-	}
-      pos = request->last_ftp_response + 4;
-      while (!isdigit ((int) *pos) && *pos != '\0')
-        pos++;
-      if (*pos == '\0')
-        {
-          gftp_disconnect (request);
-          close (sock);
-          return (-2);
-        }
-      if (sscanf (pos, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
-                  &temp[3], &temp[4], &temp[5]) != 6)
-        {
-          gftp_disconnect (request);
-          close (sock);
-          return (-2);
-        }
-      for (i = 0; i < 6; i++)
-        ad[i] = (unsigned char) (temp[i] & 0xff);
-
-      memcpy (&data_addr.sin_addr, &ad[0], 4);
-      memcpy (&data_addr.sin_port, &ad[4], 2);
-      if (connect (sock, (struct sockaddr *) &data_addr, data_addr_len) == -1)
-        {
-          request->logging_function (gftp_logging_error, request->user_data,
-                                    _("Cannot create a data connection: %s\n"),
-                                    g_strerror (errno));
-          gftp_disconnect (request);
-          close (sock);
-          return (-1);
-	}
-    }
-  else
-    {
-      getsockname (fileno (request->sockfd), (struct sockaddr *) &data_addr,
-		   &data_addr_len);
-      data_addr.sin_port = 0;
-      if (bind (sock, (struct sockaddr *) &data_addr, data_addr_len) == -1)
-	{
-	  request->logging_function (gftp_logging_error, request->user_data,
-				     _("Cannot bind a port: %s\n"),
-				     g_strerror (errno));
-          gftp_disconnect (request);
-	  close (sock);
-	  return (-1);
-	}
-
-      getsockname (sock, (struct sockaddr *) &data_addr, &data_addr_len);
-      if (listen (sock, 1) == -1)
-	{
-	  request->logging_function (gftp_logging_error, request->user_data,
-				     _("Cannot listen on port %d: %s\n"),
-				     ntohs (data_addr.sin_port),
-				     g_strerror (errno));
-          gftp_disconnect (request);
-	  close (sock);
-	  return (-1);
-	}
-      pos = (char *) &data_addr.sin_addr;
-      pos1 = (char *) &data_addr.sin_port;
-      command = g_strdup_printf ("PORT %u,%u,%u,%u,%u,%u\r\n",
-				 pos[0] & 0xff, pos[1] & 0xff, pos[2] & 0xff,
-				 pos[3] & 0xff, pos1[0] & 0xff,
-				 pos1[1] & 0xff);
-      resp = rfc959_send_command (request, command);
-      g_free (command);
-      if (resp != '2')
-	{
-          gftp_disconnect (request);
-	  close (sock);
-	  return (-2);
-	}
-    }
-
-  if ((request->datafd = fdopen (sock, "rb+")) == NULL)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                                 _("Cannot fdopen() socket: %s\n"),
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (-2);
-    }
-
-  return (0);
-}
-
-
-static int
-rfc959_accept_active_connection (gftp_request * request)
-{
-  struct sockaddr_in cli_addr;
-  size_t cli_addr_len;
-  int infd;
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
-  g_return_val_if_fail (request->datafd != NULL, -2);
-  g_return_val_if_fail (request->transfer_type == gftp_transfer_active, -2);
-
-  cli_addr_len = sizeof (cli_addr);
-  if ((infd = accept (fileno (request->datafd), (struct sockaddr *) &cli_addr,
-       &cli_addr_len)) == -1)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                                _("Cannot accept connection from server: %s\n"),
-                                g_strerror (errno));
-      gftp_disconnect (request);
-      return (-1);
-    }
-
-  fclose (request->datafd);
-
-  if ((request->datafd = fdopen (infd, "rb+")) == NULL)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                                 _("Cannot fdopen() socket: %s\n"),
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (-2);
-    }
-  return (0);
-}
-
-
-static int
-rfc959_send_command (gftp_request * request, const char *command)
-{
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
-  g_return_val_if_fail (command != NULL, -2);
-  g_return_val_if_fail (request->sockfd != NULL, -2);
-
-  if (strncmp (command, "PASS", 4) == 0)
-    {
-      request->logging_function (gftp_logging_send, request->user_data, 
-                                 "PASS xxxx\n");
-    }
-  else if (strncmp (command, "ACCT", 4) == 0)
-    {
-      request->logging_function (gftp_logging_send, request->user_data, 
-                                 "ACCT xxxx\n");
-    }
-  else
-    {
-      request->logging_function (gftp_logging_send, request->user_data, "%s",
-                                 command);
-    }
-
-  if (gftp_fwrite (request, command, strlen (command), 
-                   request->sockfd_write) < 0)
-    return (-1);
-
-  return (rfc959_read_response (request));
-}
-
-
-static int
-rfc959_read_response (gftp_request * request)
-{
-  char tempstr[255], code[4];
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
-  g_return_val_if_fail (request->sockfd != NULL, -2);
-
-  *code = '\0';
-  if (request->last_ftp_response)
-    {
-      g_free (request->last_ftp_response);
-      request->last_ftp_response = NULL;
-    }
-
-  do
-    {
-      if (!gftp_fgets (request, tempstr, sizeof (tempstr), request->sockfd))
-	break;
-      tempstr[strlen (tempstr) - 1] = '\0';
-      if (tempstr[strlen (tempstr) - 1] == '\r')
-	tempstr[strlen (tempstr) - 1] = '\0';
-      if (isdigit ((int) *tempstr) && isdigit ((int) *(tempstr + 1))
-	  && isdigit ((int) *(tempstr + 2)))
-	{
-	  strncpy (code, tempstr, 3);
-	  code[3] = ' ';
-	}
-      request->logging_function (gftp_logging_recv, request->user_data,
-				 "%s\n", tempstr);
-    }
-  while (strncmp (code, tempstr, 4) != 0);
-
-  if (ferror (request->sockfd)) 
-    {
-      request->logging_function (gftp_logging_send, request->user_data,
-                                 "Error reading from socket: %s\n",
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (-1);
-    }
-
-  request->last_ftp_response = g_malloc (strlen (tempstr) + 1);
-  strcpy (request->last_ftp_response, tempstr);
-
-  if (request->last_ftp_response[0] == '4' &&
-      request->last_ftp_response[1] == '2')
-    gftp_disconnect (request);
-
-  return (*request->last_ftp_response);
-}
-
-
-static int
-rfc959_chdir (gftp_request * request, const char *directory)
-{
-  char ret, *tempstr, *dir;
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2);
-  g_return_val_if_fail (directory != NULL, -2);
-
-  if (strcmp (directory, "..") == 0)
-    ret = rfc959_send_command (request, "CDUP\r\n");
-  else
-    {
-      tempstr = g_strconcat ("CWD ", directory, "\r\n", NULL);
-      ret = rfc959_send_command (request, tempstr);
-      g_free (tempstr);
-    }
-
-  if (ret != '2')
-    return (-2);
-
-  if (directory != request->directory)
-    {
-      if (request->directory)
-        {
-          g_free (request->directory);
-          request->directory = NULL;
-        }
-
-      if (rfc959_send_command (request, "PWD\r\n") != '2')
-        return (-2);
-
-      tempstr = strchr (request->last_ftp_response, '"');
-      if (tempstr != NULL)
-        dir = tempstr + 1;
-      else
-        return (-2);
-
-      tempstr = strchr (dir, '"');
-      if (tempstr != NULL)
-        *tempstr = '\0';
-      else
-        {
-          gftp_disconnect (request);
-          return (-2);
-        }
-
-      request->directory = g_malloc (strlen (dir) + 1);
-      strcpy (request->directory, dir);
-    }
-
-  return (0);
-}
-
-
-static int
 rfc959_rmdir (gftp_request * request, const char *directory)
 {
   char *tempstr, ret;
@@ -1070,101 +1081,43 @@
 }
 
 
-static char *
-parse_ftp_proxy_string (gftp_request * request)
+void
+rfc959_init (gftp_request * request)
 {
-  char *startpos, *endpos, *oldstr, *newstr, *newval, *tempport;
-
-  g_return_val_if_fail (request != NULL, NULL);
-  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, NULL);
+  g_return_if_fail (request != NULL);
 
-  newstr = g_malloc (1);
-  *newstr = '\0';
-  startpos = endpos = request->proxy_config;
-  while (*endpos != '\0')
-    {
-      tempport = NULL;
-      if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'p')
-	{
-	  switch (tolower ((int) *(endpos + 2)))
-	    {
-	    case 'u':
-	      newval = request->proxy_username;
-	      break;
-	    case 'p':
-	      newval = request->proxy_password;
-	      break;
-	    case 'h':
-	      newval = request->proxy_hostname;
-	      break;
-	    case 'o':
-	      tempport = g_strdup_printf ("%d", request->proxy_port);
-	      newval = tempport;
-	      break;
-	    case 'a':
-	      newval = request->proxy_account;
-	      break;
-	    default:
-	      endpos++;
-	      continue;
-	    }
-	}
-      else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'h')
-	{
-	  switch (tolower ((int) *(endpos + 2)))
-	    {
-	    case 'u':
-	      newval = request->username;
-	      break;
-	    case 'p':
-	      newval = request->password;
-	      break;
-	    case 'h':
-	      newval = request->hostname;
-	      break;
-	    case 'o':
-	      tempport = g_strdup_printf ("%d", request->port);
-	      newval = tempport;
-	      break;
-	    case 'a':
-	      newval = request->account;
-	      break;
-	    default:
-	      endpos++;
-	      continue;
-	    }
-	}
-      else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'n')
-	{
-	  *endpos = '\0';
-	  oldstr = newstr;
-	  newstr = g_strconcat (oldstr, startpos, "\r\n", NULL);
-	  g_free (oldstr);
-	  endpos += 2;
-	  startpos = endpos;
-	  continue;
-	}
-      else
-	{
-	  endpos++;
-	  continue;
-	}
-
-      *endpos = '\0';
-      oldstr = newstr;
-      if (!newval)
-	newstr = g_strconcat (oldstr, startpos, NULL);
-      else
-	newstr = g_strconcat (oldstr, startpos, newval, NULL);
-      if (tempport)
-	{
-	  g_free (tempport);
-	  tempport = NULL;
-	}
-      g_free (oldstr);
-      endpos += 3;
-      startpos = endpos;
-    }
-  return (newstr);
+  request->protonum = GFTP_FTP_NUM;
+  request->init = rfc959_init;
+  request->destroy = NULL; 
+  request->connect = rfc959_connect;
+  request->disconnect = rfc959_disconnect;
+  request->get_file = rfc959_get_file;
+  request->put_file = rfc959_put_file;
+  request->transfer_file = rfc959_transfer_file;
+  request->get_next_file_chunk = NULL;
+  request->put_next_file_chunk = NULL;
+  request->end_transfer = rfc959_end_transfer;
+  request->abort_transfer = rfc959_abort_transfer;
+  request->list_files = rfc959_list_files;
+  request->get_next_file = rfc959_get_next_file;
+  request->set_data_type = rfc959_set_data_type;
+  request->get_file_size = rfc959_get_file_size;
+  request->chdir = rfc959_chdir;
+  request->rmdir = rfc959_rmdir;
+  request->rmfile = rfc959_rmfile;
+  request->mkdir = rfc959_mkdir;
+  request->rename = rfc959_rename;
+  request->chmod = rfc959_chmod;
+  request->set_file_time = NULL;
+  request->site = rfc959_site;
+  request->parse_url = NULL;
+  request->url_prefix = "ftp";
+  request->protocol_name = "FTP";
+  request->need_hostport = 1;
+  request->need_userpass = 1;
+  request->use_cache = 1;
+  request->use_threads = 1;
+  request->always_connected = 0;
+  gftp_set_config_options (request);
 }
 
--- a/lib/ssh.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/ssh.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,6 +20,10 @@
 /* This will use Brian Wellington <bwelling@xbill.org>'s sftpserv program */
 /* on the remote. Some of this code is derived from the sftp client */
 
+/* 11/5/2002 - This protocol is now obsolete by the SSH2 protocol. I'm not 
+   going to be adding any new features to it, but I'll keep it inside the code 
+   for a little bit. I do plan on removing it completely though */
+
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
@@ -63,105 +67,217 @@
 } ssh_message;
 
 
-static void ssh_destroy 		( gftp_request * request );
-static int ssh_connect 			( gftp_request * request );
-static void ssh_disconnect 		( gftp_request * request );
-static long ssh_get_file 		( gftp_request * request, 
-					  const char *filename,
-					  FILE * fd,
-					  off_t startsize );
-static int ssh_put_file 		( gftp_request * request, 
-					  const char *filename,
-					  FILE * fd,
-					  off_t startsize,
-					  off_t totalsize );
-static size_t ssh_get_next_file_chunk 	( gftp_request * request, 
-					  char *buf, 
-					  size_t size );
-static size_t ssh_put_next_file_chunk 	( gftp_request * request, 
-					  char *buf, 
-					  size_t size );
-static int ssh_end_transfer 		( gftp_request * request );
-static int ssh_list_files 		( gftp_request * request );
-static int ssh_get_next_file 		( gftp_request * request, 
-					  gftp_file * fle, 
-					  FILE * fd );
-static int ssh_chdir 			( gftp_request * request, 
-					  const char *directory );
-static char *ssh_exec			( gftp_request * request,
-					  const char *command,
-					  size_t len);
-static int ssh_rmdir			( gftp_request * request, 
-					  const char *directory );
-static int ssh_rmfile			( gftp_request * request, 
-					  const char *file );
-static int ssh_mkdir			( gftp_request * request, 
-					  const char *newdir );
-static int ssh_rename			( gftp_request * request,
-					  const char *oldname,
-					  const char *newname );
-static int ssh_chmod			( gftp_request * request,
-					  const char *file,
-					  int mode );
-static int ssh_send_command 		( gftp_request * request, 
-					  int cmdnum, 
-					  const char *command, 
-					  size_t len );
-static int ssh_read_response 		( gftp_request * request, 
-					  ssh_message *message,
-					  FILE * fd );
-static char *ssh_read_message 		( gftp_request * request, 
-					  char *buf, 
-					  size_t len,
-					  FILE * fd );
-static char *ssh_read_line 		( gftp_request * request );
-static void ssh_log_command 		( gftp_request * request,
-					  int channel,
-					  int cmdnum, 
-					  const char *command, 
-					  size_t len,
-					  int direction );
-static size_t ssh_remove_spaces 	( char *string );
+static void
+ssh_log_command (gftp_request * request, int channel, int cmdnum, 
+                 const char *command, size_t len, int direction)
+{
+  const char *pos;
+  char *tempstr;
+  int ok;
+
+  switch (cmdnum)
+    {
+      case CHDIR:
+        tempstr = "CHDIR ";
+        break;
+      case GETDIR:
+        tempstr = "GETDIR ";
+        break;
+      case TELLDIR:
+        tempstr = "TELLDIR ";
+        break;
+      case SENDFILE:
+        tempstr = "SENDFILE ";
+        break;
+      case FILESIZE:
+        tempstr = "FILESIZE ";
+        break;
+      case FILEMODE:
+        tempstr = "FILEMODE ";
+        break;
+      case ENDDATA:
+        tempstr = "ENDDATA ";
+        break;
+      case FILEOK:
+        tempstr = "FILEOK ";
+        break;
+      case STREAM:
+        tempstr = "STREAM ";
+        break;
+      case REQUEST:
+        tempstr = "REQUEST ";
+        break;
+      case FILENAME:
+        tempstr = "FILENAME ";
+        break;
+      case EXEC:
+        tempstr = "EXEC ";
+        break;
+      case SKIPBYTES:
+        tempstr = "SKIPBYTES ";
+        break;
+      case ERROR:
+        tempstr = "ERROR: ";
+        break;
+      case SUCCESS:
+        tempstr = "SUCCESS ";
+        break;
+      case CLOSE:
+        tempstr = "CLOSE ";
+        break;
+      case SSH_VERSION:
+        tempstr = "VERSION ";
+        break;
+      case CANCEL:
+        tempstr = "CANCEL ";
+        break;
+      case FILETIME:
+        tempstr = "FILETIME ";
+        break;
+      default:
+        return;
+    }
+
+  ok = 0;
+  if (command)
+    {
+      for (pos = command; pos < command + len; pos++)
+        {
+          if (*pos == '\0')
+            {
+              ok = 1;
+              break;
+            }
+        }
+    }
+
+  request->logging_function (direction == GFTP_DIRECTION_DOWNLOAD ? 
+                                 gftp_logging_send : gftp_logging_recv,
+                             request->user_data, "%d: %s %s\n", channel, 
+                             tempstr, ok ? command : "");
+}
+
+
+static int
+ssh_send_command (gftp_request * request, int cmdnum, const char *command, 
+                  size_t len)
+{
+  ssh_parms * params;
+  char *buf;
+  int clen;
 
-void
-ssh_init (gftp_request * request)
+  params = request->protocol_data;
+  clen = htonl (len);
+  buf = g_malloc (len + 6);
+  buf[0] = params->channel;
+  buf[1] = cmdnum;
+  memcpy (&buf[2], &clen, 4);
+  if (command)
+    memcpy (&buf[6], command, len);
+  ssh_log_command (request, params->channel, cmdnum, command, len, 1);
+
+  if (gftp_fwrite (request, buf, len + 6, request->sockfd_write) < 0)
+    return (-2);
+
+  return 0;
+
+}
+
+
+static char *
+ssh_read_message (gftp_request * request, char *buf, size_t len, FILE * fd)
 {
-  g_return_if_fail (request != NULL);
+  if (fd == NULL)
+    fd = request->sockfd;
+
+  fread (buf, len, 1, fd);
+  if (ferror (fd))
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error: Could not read from socket: %s\n"),
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (NULL);
+    }
+
+  return (buf);
+}
+
+
+static int
+ssh_read_response (gftp_request * request, ssh_message *message, FILE * fd)
+{
+  char buf[6];
+
+  if (ssh_read_message (request, buf, 6, fd) == NULL)
+    return (-1);
 
-  request->protonum = GFTP_SSH_NUM;
-  request->init = ssh_init;
-  request->destroy = ssh_destroy;
-  request->connect = ssh_connect;
-  request->disconnect = ssh_disconnect;
-  request->get_file = ssh_get_file;
-  request->put_file = ssh_put_file;
-  request->transfer_file = NULL;
-  request->get_next_file_chunk = ssh_get_next_file_chunk;
-  request->put_next_file_chunk = ssh_put_next_file_chunk;
-  request->end_transfer = ssh_end_transfer;
-  request->abort_transfer = NULL; /* FIXME */
-  request->list_files = ssh_list_files;
-  request->get_next_file = ssh_get_next_file;
-  request->set_data_type = NULL;
-  request->get_file_size = NULL;
-  request->chdir = ssh_chdir;
-  request->rmdir = ssh_rmdir;
-  request->rmfile = ssh_rmfile;
-  request->mkdir = ssh_mkdir;
-  request->rename = ssh_rename;
-  request->chmod = ssh_chmod;
-  request->set_file_time = NULL;
-  request->site = NULL;
-  request->parse_url = NULL;
-  request->url_prefix = "ssh";
-  request->protocol_name = "SSH";
-  request->need_hostport = 1;
-  request->need_userpass = ssh_need_userpass;
-  request->use_cache = 1;
-  request->use_threads = 1;
-  request->always_connected = 0;
-  request->protocol_data = g_malloc0 (sizeof (ssh_parms));
-  gftp_set_config_options (request);
+  message->channel = buf[0];
+  message->command = buf[1];
+  memcpy (&message->len, buf + 2, 4);
+  message->len = ntohl (message->len);
+  if (message->len > 8192)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                             _("Error: Message size %d too big from server\n"),
+                             message->len);
+      memset (message, 0, sizeof (*message));
+      gftp_disconnect (request);
+      return (-1);
+    }
+  
+  message->data = g_malloc (message->len + 1); 
+
+  if (message->len > 0 && ssh_read_message (request, 
+                           (char *) message->data, message->len, fd) == NULL)
+    return (-1);
+
+  ((char *) message->data)[message->len] = '\0'; 
+  ssh_log_command (request, message->channel, message->command, message->data,
+                   message->len, 0);
+  return (message->command);
+}
+
+
+static char *
+ssh_read_line (gftp_request * request)
+{
+  char *retstr, *pos, tempchar;
+  ssh_parms *buffer;
+
+  pos = NULL;
+  buffer = request->protocol_data;
+  if (!buffer->enddata && (pos = strchr (buffer->pos, '\n')) == NULL)
+    return (NULL);
+
+  if (pos == NULL)
+    {
+      pos = buffer->pos + strlen (buffer->pos) - 1;
+      tempchar = '\0';
+    }
+  else
+    tempchar = pos + 1 == '\0' ? '\0' : '1';
+
+  if (*(pos-1) == '\r') 
+    *(pos-1) = '\0';
+  else 
+    *pos = '\0';
+
+  retstr = g_malloc (strlen (buffer->pos) + 1);
+  strcpy (retstr, buffer->pos);
+
+  if (tempchar != '\0' && *buffer->pos != '\0')
+    {
+      buffer->pos = pos + 1;
+      while (*buffer->pos == '\r' || *buffer->pos == '\n')
+        buffer->pos++;
+    }
+  else
+    {
+      g_free (buffer->buffer);
+      buffer->buffer = buffer->pos = NULL;
+    }
+  return (retstr);
 }
 
 
@@ -183,6 +299,55 @@
 
 
 static int
+ssh_chdir (gftp_request * request, const char *directory)
+{
+  ssh_message message;
+  int ret;
+
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_SSH_NUM, -2);
+
+  if (directory != NULL && *directory != '\0')
+    {  
+      if (ssh_send_command (request, CHDIR, directory, 
+                            strlen (directory) + 1) < 0) 
+        return (-1);
+
+      if ((ret = ssh_read_response (request, &message, NULL)) != SUCCESS)
+        {
+          request->logging_function (gftp_logging_error, request->user_data,
+			    _("Could not change remote directory to %s: %s\n"),
+	  	            directory, (char *) message.data);
+          g_free (message.data);
+          return (-1);
+        }
+      g_free (message.data);
+    }
+
+  if (directory != request->directory)
+    {
+      if (ssh_send_command (request, GETDIR, NULL, 0) < 0)
+        return (-1);
+
+      if (ssh_read_response (request, &message, NULL) != TELLDIR)
+        {
+          request->logging_function (gftp_logging_error, request->user_data,
+                            _("Could not get current working directory: %s\n"),
+		  	    (char *) message.data);
+          g_free (message.data);
+          return (-1);
+        }
+
+      if (request->directory)
+        g_free (request->directory);
+      request->directory = message.data;
+    }
+
+  return (0);
+}
+
+
+static int
 ssh_connect (gftp_request * request)
 {
   char **args, *tempstr, pts_name[20], *p1, p2, *exepath, port[6];
@@ -566,6 +731,21 @@
 }
 
 
+static size_t 
+ssh_remove_spaces ( char *string )
+{
+  size_t len;
+  char *pos;
+
+  for (pos = string, len = 0; *pos != '\0'; len++, pos++)
+    {
+      if (*pos == ' ')
+        *pos = '\0';
+    }
+  return (len);
+}
+
+
 static int
 ssh_list_files (gftp_request * request)
 {
@@ -733,55 +913,6 @@
 }
 
 
-static int
-ssh_chdir (gftp_request * request, const char *directory)
-{
-  ssh_message message;
-  int ret;
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_SSH_NUM, -2);
-
-  if (directory != NULL && *directory != '\0')
-    {  
-      if (ssh_send_command (request, CHDIR, directory, 
-                            strlen (directory) + 1) < 0) 
-        return (-1);
-
-      if ((ret = ssh_read_response (request, &message, NULL)) != SUCCESS)
-        {
-          request->logging_function (gftp_logging_error, request->user_data,
-			    _("Could not change remote directory to %s: %s\n"),
-	  	            directory, (char *) message.data);
-          g_free (message.data);
-          return (-1);
-        }
-      g_free (message.data);
-    }
-
-  if (directory != request->directory)
-    {
-      if (ssh_send_command (request, GETDIR, NULL, 0) < 0)
-        return (-1);
-
-      if (ssh_read_response (request, &message, NULL) != TELLDIR)
-        {
-          request->logging_function (gftp_logging_error, request->user_data,
-                            _("Could not get current working directory: %s\n"),
-		  	    (char *) message.data);
-          g_free (message.data);
-          return (-1);
-        }
-
-      if (request->directory)
-        g_free (request->directory);
-      request->directory = message.data;
-    }
-
-  return (0);
-}
-
-
 static char *
 ssh_exec (gftp_request * request, const char *command, size_t len)
 {
@@ -1007,230 +1138,45 @@
 }
 
 
-static int
-ssh_send_command (gftp_request * request, int cmdnum, const char *command, 
-                  size_t len)
+void
+ssh_init (gftp_request * request)
 {
-  ssh_parms * params;
-  char *buf;
-  int clen;
-
-  params = request->protocol_data;
-  clen = htonl (len);
-  buf = g_malloc (len + 6);
-  buf[0] = params->channel;
-  buf[1] = cmdnum;
-  memcpy (&buf[2], &clen, 4);
-  if (command)
-    memcpy (&buf[6], command, len);
-  ssh_log_command (request, params->channel, cmdnum, command, len, 1);
-
-  if (gftp_fwrite (request, buf, len + 6, request->sockfd_write) < 0)
-    return (-2);
-
-  return 0;
-
-}
-
-static int
-ssh_read_response (gftp_request * request, ssh_message *message, FILE * fd)
-{
-  char buf[6];
-
-  if (ssh_read_message (request, buf, 6, fd) == NULL)
-    return (-1);
+  g_return_if_fail (request != NULL);
 
-  message->channel = buf[0];
-  message->command = buf[1];
-  memcpy (&message->len, buf + 2, 4);
-  message->len = ntohl (message->len);
-  if (message->len > 8192)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                             _("Error: Message size %d too big from server\n"),
-                             message->len);
-      memset (message, 0, sizeof (*message));
-      gftp_disconnect (request);
-      return (-1);
-    }
-  
-  message->data = g_malloc (message->len + 1); 
-
-  if (message->len > 0 && ssh_read_message (request, 
-                           (char *) message->data, message->len, fd) == NULL)
-    return (-1);
-
-  ((char *) message->data)[message->len] = '\0'; 
-  ssh_log_command (request, message->channel, message->command, message->data,
-                   message->len, 0);
-  return (message->command);
-}
-
-
-static char *
-ssh_read_message (gftp_request * request, char *buf, size_t len, FILE * fd)
-{
-  if (fd == NULL)
-    fd = request->sockfd;
-
-  fread (buf, len, 1, fd);
-  if (ferror (fd))
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                                 _("Error: Could not read from socket: %s\n"),
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (NULL);
-    }
-
-  return (buf);
+  request->protonum = GFTP_SSH_NUM;
+  request->init = ssh_init;
+  request->destroy = ssh_destroy;
+  request->connect = ssh_connect;
+  request->disconnect = ssh_disconnect;
+  request->get_file = ssh_get_file;
+  request->put_file = ssh_put_file;
+  request->transfer_file = NULL;
+  request->get_next_file_chunk = ssh_get_next_file_chunk;
+  request->put_next_file_chunk = ssh_put_next_file_chunk;
+  request->end_transfer = ssh_end_transfer;
+  request->abort_transfer = NULL; /* FIXME */
+  request->list_files = ssh_list_files;
+  request->get_next_file = ssh_get_next_file;
+  request->set_data_type = NULL;
+  request->get_file_size = NULL;
+  request->chdir = ssh_chdir;
+  request->rmdir = ssh_rmdir;
+  request->rmfile = ssh_rmfile;
+  request->mkdir = ssh_mkdir;
+  request->rename = ssh_rename;
+  request->chmod = ssh_chmod;
+  request->set_file_time = NULL;
+  request->site = NULL;
+  request->parse_url = NULL;
+  request->url_prefix = "ssh";
+  request->protocol_name = "SSH";
+  request->need_hostport = 1;
+  request->need_userpass = ssh_need_userpass;
+  request->use_cache = 1;
+  request->use_threads = 1;
+  request->always_connected = 0;
+  request->protocol_data = g_malloc0 (sizeof (ssh_parms));
+  gftp_set_config_options (request);
 }
 
 
-static char *
-ssh_read_line (gftp_request * request)
-{
-  char *retstr, *pos, tempchar;
-  ssh_parms *buffer;
-
-  pos = NULL;
-  buffer = request->protocol_data;
-  if (!buffer->enddata && (pos = strchr (buffer->pos, '\n')) == NULL)
-    return (NULL);
-
-  if (pos == NULL)
-    {
-      pos = buffer->pos + strlen (buffer->pos) - 1;
-      tempchar = '\0';
-    }
-  else
-    tempchar = pos + 1 == '\0' ? '\0' : '1';
-
-  if (*(pos-1) == '\r') 
-    *(pos-1) = '\0';
-  else 
-    *pos = '\0';
-
-  retstr = g_malloc (strlen (buffer->pos) + 1);
-  strcpy (retstr, buffer->pos);
-
-  if (tempchar != '\0' && *buffer->pos != '\0')
-    {
-      buffer->pos = pos + 1;
-      while (*buffer->pos == '\r' || *buffer->pos == '\n')
-        buffer->pos++;
-    }
-  else
-    {
-      g_free (buffer->buffer);
-      buffer->buffer = buffer->pos = NULL;
-    }
-  return (retstr);
-}
-
-
-static void
-ssh_log_command (gftp_request * request, int channel, int cmdnum, 
-                 const char *command, size_t len, int direction)
-{
-  const char *pos;
-  char *tempstr;
-  int ok;
-
-  switch (cmdnum)
-    {
-      case CHDIR:
-        tempstr = "CHDIR ";
-        break;
-      case GETDIR:
-        tempstr = "GETDIR ";
-        break;
-      case TELLDIR:
-        tempstr = "TELLDIR ";
-        break;
-      case SENDFILE:
-        tempstr = "SENDFILE ";
-        break;
-      case FILESIZE:
-        tempstr = "FILESIZE ";
-        break;
-      case FILEMODE:
-        tempstr = "FILEMODE ";
-        break;
-      case ENDDATA:
-        tempstr = "ENDDATA ";
-        break;
-      case FILEOK:
-        tempstr = "FILEOK ";
-        break;
-      case STREAM:
-        tempstr = "STREAM ";
-        break;
-      case REQUEST:
-        tempstr = "REQUEST ";
-        break;
-      case FILENAME:
-        tempstr = "FILENAME ";
-        break;
-      case EXEC:
-        tempstr = "EXEC ";
-        break;
-      case SKIPBYTES:
-        tempstr = "SKIPBYTES ";
-        break;
-      case ERROR:
-        tempstr = "ERROR: ";
-        break;
-      case SUCCESS:
-        tempstr = "SUCCESS ";
-        break;
-      case CLOSE:
-        tempstr = "CLOSE ";
-        break;
-      case SSH_VERSION:
-        tempstr = "VERSION ";
-        break;
-      case CANCEL:
-        tempstr = "CANCEL ";
-        break;
-      case FILETIME:
-        tempstr = "FILETIME ";
-        break;
-      default:
-        return;
-    }
-
-  ok = 0;
-  if (command)
-    {
-      for (pos = command; pos < command + len; pos++)
-        {
-          if (*pos == '\0')
-            {
-              ok = 1;
-              break;
-            }
-        }
-    }
-
-  request->logging_function (direction == GFTP_DIRECTION_DOWNLOAD ? 
-                                 gftp_logging_send : gftp_logging_recv,
-                             request->user_data, "%d: %s %s\n", channel, 
-                             tempstr, ok ? command : "");
-}
-
-
-static size_t 
-ssh_remove_spaces ( char *string )
-{
-  size_t len;
-  char *pos;
-
-  for (pos = string, len = 0; *pos != '\0'; len++, pos++)
-    {
-      if (*pos == ' ')
-        *pos = '\0';
-    }
-  return (len);
-}
-
--- a/lib/sshv2.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/lib/sshv2.c	Wed Nov 06 02:20:25 2002 +0000
@@ -61,68 +61,6 @@
 } sshv2_params;
 
 
-static void sshv2_destroy 			( gftp_request * request );
-static int sshv2_connect 			( gftp_request * request );
-static void sshv2_disconnect 			( gftp_request * request );
-static gint32 sshv2_buffer_get_int32 		( gftp_request * request, 
-						  sshv2_message * buffer,
-						  int expected_response );
-static char * sshv2_buffer_get_string 		( gftp_request * request,
-						  sshv2_message * buffer );
-static int sshv2_send_command 			( gftp_request * request, 
-						  char type,
-						  char *command, 
-						  gint32 len );
-static int sshv2_read_response 			( gftp_request * request, 
-						  sshv2_message * message, 
-						  FILE * fd );
-static void sshv2_message_free 			( sshv2_message * message );
-static void sshv2_log_command 			( gftp_request * request, 
-						  gftp_logging_level level,
-						  char type,
-						  char *message,
-						  size_t length );
-static int sshv2_end_transfer 			( gftp_request * request );
-static int sshv2_list_files 			( gftp_request * request );
-static int sshv2_get_next_file 			( gftp_request * request,
-						  gftp_file * fle, 
-						  FILE * fd );
-static int sshv2_chdir                    	( gftp_request * request,
-						  const char *directory );
-static int sshv2_getcwd				( gftp_request * request );
-static int sshv2_rmdir 				( gftp_request * request, 
-						  const char *directory );
-static int sshv2_rmfile				( gftp_request * request, 
-						  const char *file);
-static int sshv2_chmod                    	( gftp_request * request,
-						  const char *file,
-						  int mode );
-static int sshv2_mkdir                    	( gftp_request * request,
-						  const char *newdir );
-static int sshv2_rename                   	( gftp_request * request,
-						  const char *oldname,
-						  const char *newname );
-static int sshv2_set_file_time                  ( gftp_request * request,
-                                                  const char *file,
-                                                  time_t datetime );
-static off_t sshv2_get_file_size 		( gftp_request * request,
-						  const char *file );
-static long sshv2_get_file                      ( gftp_request * request,
-                                                  const char *filename,
-						  FILE * fd,
-                                                  off_t startsize );
-static int sshv2_put_file 			( gftp_request * request,
-                                                  const char *filename,
-						  FILE * fd,
-                                                  off_t startsize,
-						  off_t totalsize );
-static size_t sshv2_get_next_file_chunk 	( gftp_request * request,
-						  char *buf,
-						  size_t size );
-static size_t sshv2_put_next_file_chunk 	( gftp_request * request,
-						  char *buf,
-						  size_t size );
-
 #define SSH_MY_VERSION              3
 
 #define SSH_FXP_INIT                1
@@ -175,50 +113,271 @@
 #define SSH_FX_OP_UNSUPPORTED                8
 
 
-void
-sshv2_init (gftp_request * request)
+static void
+sshv2_log_command (gftp_request * request, gftp_logging_level level,
+                   char type, char *message, size_t length)
 {
+  gint32 id, num, attr, stattype;
+  char *descr, *pos, oldchar;
   sshv2_params * params;
 
-  g_return_if_fail (request != NULL);
+  params = request->protocol_data;
+  memcpy (&id, message, 4);
+  id = ntohl (id);
+  switch (type)
+    {
+      case SSH_FXP_INIT:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Protocol Initialization\n"), id);
+        break;
+      case SSH_FXP_VERSION:
+        memcpy (&num, message, 4);
+        num = ntohl (num);
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Protocol version %d\n"), id, num);
+        break;
+      case SSH_FXP_OPEN:
+        memcpy (&num, message + 4, 4);
+        num = ntohl (num);
+        pos = message + 12 + num - 1;
+        oldchar = *pos;
+        *pos = '\0';
+        request->logging_function (level, request->user_data,
+                                   _("%d: Open %s\n"), id, message + 8);
+        *pos = oldchar;
+        break;
+      case SSH_FXP_CLOSE:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Close\n"), id);
+      case SSH_FXP_READ:
+      case SSH_FXP_WRITE:
+        break;  
+      case SSH_FXP_OPENDIR:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Open Directory %s\n"), id,
+                                   message + 8);
+        break;
+      case SSH_FXP_READDIR:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Read Directory\n"), id);
+        break;
+      case SSH_FXP_REMOVE:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Remove file %s\n"), id,
+                                   message + 8);
+        break;
+      case SSH_FXP_MKDIR:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Make directory %s\n"), id,
+                                   message + 8);
+        break;
+      case SSH_FXP_RMDIR:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Remove directory %s\n"), id,
+                                   message + 8);
+        break;
+      case SSH_FXP_REALPATH:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Realpath %s\n"), id,
+                                   message + 8);
+        break;
+      case SSH_FXP_ATTRS:
+        request->logging_function (level, request->user_data,
+                                   _("%d: File attributes\n"), id);
+        break;
+      case SSH_FXP_STAT:
+        request->logging_function (level, request->user_data, 
+                                   _("%d: Stat %s\n"), id,
+                                   message + 8);
+        break;
+      case SSH_FXP_SETSTAT:
+        memcpy (&num, message + 4, 4);
+        num = ntohl (num);
+        pos = message + 12 + num - 1;
+        oldchar = *pos;
+        *pos = '\0';
+        memcpy (&stattype, message + 8 + num, 4);
+        stattype = ntohl (stattype);
+        memcpy (&attr, message + 12 + num, 4);
+        attr = ntohl (attr);
+        switch (stattype)
+          {
+            case SSH_FILEXFER_ATTR_PERMISSIONS:
+              request->logging_function (level, request->user_data,
+                                         _("%d: Chmod %s %o\n"), id,
+                                         message + 8, attr);
+              break;
+            case SSH_FILEXFER_ATTR_ACMODTIME:
+              request->logging_function (level, request->user_data,
+                                         _("%d: Utime %s %d\n"), id,
+                                         message + 8, attr);
+          }
+        *pos = oldchar;
+        break;
+      case SSH_FXP_STATUS:
+        if (params->dont_log_status)
+          break;
+        memcpy (&num, message + 4, 4);
+        num = ntohl (num);
+        switch (num)
+          {
+            case SSH_FX_OK:
+              descr = _("OK");
+              break;
+            case SSH_FX_EOF:
+              descr = _("EOF");
+              break;
+            case SSH_FX_NO_SUCH_FILE:
+              descr = _("No such file or directory");
+              break;
+            case SSH_FX_PERMISSION_DENIED:
+              descr = _("Permission denied");
+              break;
+            case SSH_FX_FAILURE:
+              descr = _("Failure");
+              break;
+            case SSH_FX_BAD_MESSAGE:
+              descr = _("Bad message");
+              break;
+            case SSH_FX_NO_CONNECTION:
+              descr = _("No connection");
+              break;
+            case SSH_FX_CONNECTION_LOST:
+              descr = _("Connection lost");
+              break;
+            case SSH_FX_OP_UNSUPPORTED:
+              descr = _("Operation unsupported");
+              break;
+            default:
+              descr = _("Unknown message returned from server");
+              break;
+          }
+        request->logging_function (level, request->user_data,
+                                   "%d: %s\n", id, descr);
+        break;
+      case SSH_FXP_HANDLE:
+        request->logging_function (level, request->user_data, 
+                                   "%d: File handle\n", id);
+        break;
+      case SSH_FXP_DATA:
+        break;
+      case SSH_FXP_NAME:
+        memcpy (&num, message + 4, 4);
+        num = ntohl (num);
+        request->logging_function (level, request->user_data, 
+                                   "%d: Filenames (%d entries)\n", id,
+                                   num);
+        break;
+      default:
+        request->logging_function (level, request->user_data, 
+                                   "Command: %x\n", type);
+    }
+}
 
-  request->protonum = GFTP_SSHV2_NUM;
-  request->init = sshv2_init;
-  request->destroy = sshv2_destroy;
-  request->connect = sshv2_connect;
-  request->disconnect = sshv2_disconnect;
-  request->get_file = sshv2_get_file;
-  request->put_file = sshv2_put_file;
-  request->transfer_file = NULL;
-  request->get_next_file_chunk = sshv2_get_next_file_chunk;
-  request->put_next_file_chunk = sshv2_put_next_file_chunk;
-  request->end_transfer = sshv2_end_transfer;
-  request->abort_transfer = NULL; /* FIXME */
-  request->list_files = sshv2_list_files;
-  request->get_next_file = sshv2_get_next_file;
-  request->set_data_type = NULL;
-  request->get_file_size = sshv2_get_file_size;
-  request->chdir = sshv2_chdir;
-  request->rmdir = sshv2_rmdir;
-  request->rmfile = sshv2_rmfile;
-  request->mkdir = sshv2_mkdir;
-  request->rename = sshv2_rename;
-  request->chmod = sshv2_chmod;
-  request->set_file_time = sshv2_set_file_time;
-  request->site = NULL;
-  request->parse_url = NULL;
-  request->url_prefix = "ssh2";
-  request->protocol_name = "SSH2";
-  request->need_hostport = 1;
-  request->need_userpass = ssh_need_userpass;
-  request->use_cache = 1;
-  request->use_threads = 1;
-  request->always_connected = 0;
-  request->protocol_data = g_malloc0 (sizeof (sshv2_params));
-  gftp_set_config_options (request);
+
+static int
+sshv2_send_command (gftp_request * request, char type, char *command, 
+                    gint32 len)
+{
+  char buf[34000];
+  gint32 clen;
+
+  if (len > 33995)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                             _("Error: Message size %d too big\n"), len);
+      gftp_disconnect (request);
+      return (-1);
+    }
+
+  clen = htonl (len + 1);
+  memcpy (buf, &clen, 4);
+  buf[4] = type;
+  memcpy (&buf[5], command, len);
+  buf[len + 5] = '\0';
+
+#ifdef DEBUG
+  printf ("\rSending: ");
+  for (wrote=0; wrote<len + 5; wrote++)
+    printf ("%x ", buf[wrote]);
+  printf ("\n");
+#endif
+
+  sshv2_log_command (request, gftp_logging_send, type, buf + 5, len);
+
+  if (gftp_fwrite (request, buf, len + 5, request->sockfd_write) < 0)
+    return (-2);
+
+  return 0;
+}
+
+
+static int
+sshv2_read_response (gftp_request * request, sshv2_message * message,
+                     FILE * fd)
+{
+  ssize_t numread;
+  char buf[5];
+
+  if (fd == NULL)
+    fd = request->sockfd;
 
-  params = request->protocol_data;
-  params->id = 1;
+  numread = fread (buf, 5, 1, fd);
+  if (ferror (fd))
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error: Could not read from socket: %s\n"),
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (-1);
+    }
+
+#ifdef DEBUG
+  printf ("\rReceived: ");
+  for (numread=0; numread<5; numread++)
+    printf ("%x ", buf[numread]);
+  fflush (stdout);
+#endif
+
+  memcpy (&message->length, buf, 4);
+  message->length = ntohl (message->length);
+  if (message->length > 34000)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                             _("Error: Message size %d too big from server\n"),
+                             message->length);
+      memset (message, 0, sizeof (*message));
+      gftp_disconnect (request);
+      return (-1);
+    }
+  message->command = buf[4];
+  message->buffer = g_malloc (message->length);
+
+  message->pos = message->buffer;
+  message->end = message->buffer + message->length - 1;
+
+  numread = fread (message->buffer, message->length - 1, 1, fd);
+  if (ferror (fd))
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error: Could not read from socket: %s\n"),
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (-1);
+    }
+  message->buffer[message->length - 1] = '\0';
+
+#ifdef DEBUG
+  printf ("\rReceived: ");
+  for (numread=0; numread<message->length - 1; numread++)
+    printf ("%x ", message->buffer[numread]);
+  printf ("\n");
+#endif
+
+  sshv2_log_command (request, gftp_logging_recv, message->command, 
+                     message->buffer, message->length);
+  
+  return (message->command);
 }
 
 
@@ -233,6 +392,134 @@
 }
 
 
+static void
+sshv2_message_free (sshv2_message * message)
+{
+  if (message->buffer)
+    g_free (message->buffer);
+  memset (message, 0, sizeof (*message));
+}
+
+
+static gint32
+sshv2_buffer_get_int32 (gftp_request * request, sshv2_message * message,
+                        int expected_response)
+{
+  gint32 ret;
+
+  if (message->end - message->pos < 4)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                     _("Received wrong response from server, disconnecting\n"));
+      sshv2_message_free (message);
+      gftp_disconnect (request);
+      return (-2);
+    }
+
+  memcpy (&ret, message->pos, 4);
+  ret = ntohl (ret);
+  message->pos += 4;
+
+  if (expected_response > 0 && ret != expected_response)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                     _("Received wrong response from server, disconnecting\n"));
+      sshv2_message_free (message);
+      gftp_disconnect (request);
+      return (-2);
+    }
+
+  return (ret);
+}
+
+
+static char *
+sshv2_buffer_get_string (gftp_request * request, sshv2_message * message)
+{
+  char *string;
+  gint32 len;
+
+  if ((len = sshv2_buffer_get_int32 (request, message, -1)) < 0)
+    return (NULL);
+
+  if (len > SSH_MAX_STRING_SIZE || (message->end - message->pos < len))
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                     _("Received wrong response from server, disconnecting\n"));
+      sshv2_message_free (message);
+      gftp_disconnect (request);
+      return (NULL);
+    }
+
+  string = g_malloc (len + 1);
+  memcpy (string, message->pos, len);
+  string[len] = '\0';
+  message->pos += len;
+  return (string);
+}
+
+
+static int
+sshv2_getcwd (gftp_request * request)
+{
+  sshv2_message message;
+  sshv2_params * params;
+  char *tempstr, *dir;
+  gint32 num;
+  size_t len;
+
+  g_return_val_if_fail (request != NULL, -2);
+  g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
+
+  if (request->directory == NULL || *request->directory == '\0')
+    dir = ".";
+  else
+    dir = request->directory;
+
+  params = request->protocol_data;
+  len = strlen (dir);
+  tempstr = g_malloc (len + 9);
+  strcpy (tempstr + 8, dir);
+
+  num = htonl (params->id++);
+  memcpy (tempstr, &num, 4);
+
+  num = htonl (len);
+  memcpy (tempstr + 4, &num, 4);
+  if (sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len + 8) < 0)
+    {
+      g_free (tempstr);
+      return (-2);
+    }
+
+  g_free (tempstr);
+  if (request->directory)
+    {
+      g_free (request->directory);
+      request->directory = NULL;
+    }
+
+  memset (&message, 0, sizeof (message));
+  if (sshv2_read_response (request, &message, NULL) != SSH_FXP_NAME)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                     _("Received wrong response from server, disconnecting\n"));
+      sshv2_message_free (&message);
+      gftp_disconnect (request);
+      return (-2);
+    }
+
+  message.pos += 4;
+  if (sshv2_buffer_get_int32 (request, &message, 1) < 0)
+    return (-2);
+
+  if ((request->directory = sshv2_buffer_get_string (request, &message)) == NULL)
+    return (-2);
+  sshv2_message_free (&message);
+  return (0);
+}
+
+
 static int
 sshv2_connect (gftp_request * request)
 {
@@ -436,341 +723,6 @@
 }
 
 
-static gint32
-sshv2_buffer_get_int32 (gftp_request * request, sshv2_message * message,
-                        int expected_response)
-{
-  gint32 ret;
-
-  if (message->end - message->pos < 4)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                     _("Received wrong response from server, disconnecting\n"));
-      sshv2_message_free (message);
-      gftp_disconnect (request);
-      return (-2);
-    }
-
-  memcpy (&ret, message->pos, 4);
-  ret = ntohl (ret);
-  message->pos += 4;
-
-  if (expected_response > 0 && ret != expected_response)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                     _("Received wrong response from server, disconnecting\n"));
-      sshv2_message_free (message);
-      gftp_disconnect (request);
-      return (-2);
-    }
-
-  return (ret);
-}
-
-
-static char *
-sshv2_buffer_get_string (gftp_request * request, sshv2_message * message)
-{
-  char *string;
-  gint32 len;
-
-  if ((len = sshv2_buffer_get_int32 (request, message, -1)) < 0)
-    return (NULL);
-
-  if (len > SSH_MAX_STRING_SIZE || (message->end - message->pos < len))
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                     _("Received wrong response from server, disconnecting\n"));
-      sshv2_message_free (message);
-      gftp_disconnect (request);
-      return (NULL);
-    }
-
-  string = g_malloc (len + 1);
-  memcpy (string, message->pos, len);
-  string[len] = '\0';
-  message->pos += len;
-  return (string);
-}
-
-
-static int
-sshv2_send_command (gftp_request * request, char type, char *command, 
-                    gint32 len)
-{
-  char buf[34000];
-  gint32 clen;
-
-  if (len > 33995)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                             _("Error: Message size %d too big\n"), len);
-      gftp_disconnect (request);
-      return (-1);
-    }
-
-  clen = htonl (len + 1);
-  memcpy (buf, &clen, 4);
-  buf[4] = type;
-  memcpy (&buf[5], command, len);
-  buf[len + 5] = '\0';
-
-#ifdef DEBUG
-  printf ("\rSending: ");
-  for (wrote=0; wrote<len + 5; wrote++)
-    printf ("%x ", buf[wrote]);
-  printf ("\n");
-#endif
-
-  sshv2_log_command (request, gftp_logging_send, type, buf + 5, len);
-
-  if (gftp_fwrite (request, buf, len + 5, request->sockfd_write) < 0)
-    return (-2);
-
-  return 0;
-}
-
-
-static int
-sshv2_read_response (gftp_request * request, sshv2_message * message,
-                     FILE * fd)
-{
-  ssize_t numread;
-  char buf[5];
-
-  if (fd == NULL)
-    fd = request->sockfd;
-
-  numread = fread (buf, 5, 1, fd);
-  if (ferror (fd))
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                                 _("Error: Could not read from socket: %s\n"),
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (-1);
-    }
-
-#ifdef DEBUG
-  printf ("\rReceived: ");
-  for (numread=0; numread<5; numread++)
-    printf ("%x ", buf[numread]);
-  fflush (stdout);
-#endif
-
-  memcpy (&message->length, buf, 4);
-  message->length = ntohl (message->length);
-  if (message->length > 34000)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                             _("Error: Message size %d too big from server\n"),
-                             message->length);
-      memset (message, 0, sizeof (*message));
-      gftp_disconnect (request);
-      return (-1);
-    }
-  message->command = buf[4];
-  message->buffer = g_malloc (message->length);
-
-  message->pos = message->buffer;
-  message->end = message->buffer + message->length - 1;
-
-  numread = fread (message->buffer, message->length - 1, 1, fd);
-  if (ferror (fd))
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                                 _("Error: Could not read from socket: %s\n"),
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (-1);
-    }
-  message->buffer[message->length - 1] = '\0';
-
-#ifdef DEBUG
-  printf ("\rReceived: ");
-  for (numread=0; numread<message->length - 1; numread++)
-    printf ("%x ", message->buffer[numread]);
-  printf ("\n");
-#endif
-
-  sshv2_log_command (request, gftp_logging_recv, message->command, 
-                     message->buffer, message->length);
-  
-  return (message->command);
-}
-
-
-static void
-sshv2_message_free (sshv2_message * message)
-{
-  if (message->buffer)
-    g_free (message->buffer);
-  memset (message, 0, sizeof (*message));
-}
-
-
-static void
-sshv2_log_command (gftp_request * request, gftp_logging_level level,
-                   char type, char *message, size_t length)
-{
-  gint32 id, num, attr, stattype;
-  char *descr, *pos, oldchar;
-  sshv2_params * params;
-
-  params = request->protocol_data;
-  memcpy (&id, message, 4);
-  id = ntohl (id);
-  switch (type)
-    {
-      case SSH_FXP_INIT:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Protocol Initialization\n"), id);
-        break;
-      case SSH_FXP_VERSION:
-        memcpy (&num, message, 4);
-        num = ntohl (num);
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Protocol version %d\n"), id, num);
-        break;
-      case SSH_FXP_OPEN:
-        memcpy (&num, message + 4, 4);
-        num = ntohl (num);
-        pos = message + 12 + num - 1;
-        oldchar = *pos;
-        *pos = '\0';
-        request->logging_function (level, request->user_data,
-                                   _("%d: Open %s\n"), id, message + 8);
-        *pos = oldchar;
-        break;
-      case SSH_FXP_CLOSE:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Close\n"), id);
-      case SSH_FXP_READ:
-      case SSH_FXP_WRITE:
-        break;  
-      case SSH_FXP_OPENDIR:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Open Directory %s\n"), id,
-                                   message + 8);
-        break;
-      case SSH_FXP_READDIR:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Read Directory\n"), id);
-        break;
-      case SSH_FXP_REMOVE:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Remove file %s\n"), id,
-                                   message + 8);
-        break;
-      case SSH_FXP_MKDIR:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Make directory %s\n"), id,
-                                   message + 8);
-        break;
-      case SSH_FXP_RMDIR:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Remove directory %s\n"), id,
-                                   message + 8);
-        break;
-      case SSH_FXP_REALPATH:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Realpath %s\n"), id,
-                                   message + 8);
-        break;
-      case SSH_FXP_ATTRS:
-        request->logging_function (level, request->user_data,
-                                   _("%d: File attributes\n"), id);
-        break;
-      case SSH_FXP_STAT:
-        request->logging_function (level, request->user_data, 
-                                   _("%d: Stat %s\n"), id,
-                                   message + 8);
-        break;
-      case SSH_FXP_SETSTAT:
-        memcpy (&num, message + 4, 4);
-        num = ntohl (num);
-        pos = message + 12 + num - 1;
-        oldchar = *pos;
-        *pos = '\0';
-        memcpy (&stattype, message + 8 + num, 4);
-        stattype = ntohl (stattype);
-        memcpy (&attr, message + 12 + num, 4);
-        attr = ntohl (attr);
-        switch (stattype)
-          {
-            case SSH_FILEXFER_ATTR_PERMISSIONS:
-              request->logging_function (level, request->user_data,
-                                         _("%d: Chmod %s %o\n"), id,
-                                         message + 8, attr);
-              break;
-            case SSH_FILEXFER_ATTR_ACMODTIME:
-              request->logging_function (level, request->user_data,
-                                         _("%d: Utime %s %d\n"), id,
-                                         message + 8, attr);
-          }
-        *pos = oldchar;
-        break;
-      case SSH_FXP_STATUS:
-        if (params->dont_log_status)
-          break;
-        memcpy (&num, message + 4, 4);
-        num = ntohl (num);
-        switch (num)
-          {
-            case SSH_FX_OK:
-              descr = _("OK");
-              break;
-            case SSH_FX_EOF:
-              descr = _("EOF");
-              break;
-            case SSH_FX_NO_SUCH_FILE:
-              descr = _("No such file or directory");
-              break;
-            case SSH_FX_PERMISSION_DENIED:
-              descr = _("Permission denied");
-              break;
-            case SSH_FX_FAILURE:
-              descr = _("Failure");
-              break;
-            case SSH_FX_BAD_MESSAGE:
-              descr = _("Bad message");
-              break;
-            case SSH_FX_NO_CONNECTION:
-              descr = _("No connection");
-              break;
-            case SSH_FX_CONNECTION_LOST:
-              descr = _("Connection lost");
-              break;
-            case SSH_FX_OP_UNSUPPORTED:
-              descr = _("Operation unsupported");
-              break;
-            default:
-              descr = _("Unknown message returned from server");
-              break;
-          }
-        request->logging_function (level, request->user_data,
-                                   "%d: %s\n", id, descr);
-        break;
-      case SSH_FXP_HANDLE:
-        request->logging_function (level, request->user_data, 
-                                   "%d: File handle\n", id);
-        break;
-      case SSH_FXP_DATA:
-        break;
-      case SSH_FXP_NAME:
-        memcpy (&num, message + 4, 4);
-        num = ntohl (num);
-        request->logging_function (level, request->user_data, 
-                                   "%d: Filenames (%d entries)\n", id,
-                                   num);
-        break;
-      default:
-        request->logging_function (level, request->user_data, 
-                                   "Command: %x\n", type);
-    }
-}
-
-
 static int
 sshv2_end_transfer (gftp_request * request)
 {
@@ -1144,67 +1096,6 @@
 }
 
 
-static int
-sshv2_getcwd (gftp_request * request)
-{
-  sshv2_message message;
-  sshv2_params * params;
-  char *tempstr, *dir;
-  gint32 num;
-  size_t len;
-
-  g_return_val_if_fail (request != NULL, -2);
-  g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
-
-  if (request->directory == NULL || *request->directory == '\0')
-    dir = ".";
-  else
-    dir = request->directory;
-
-  params = request->protocol_data;
-  len = strlen (dir);
-  tempstr = g_malloc (len + 9);
-  strcpy (tempstr + 8, dir);
-
-  num = htonl (params->id++);
-  memcpy (tempstr, &num, 4);
-
-  num = htonl (len);
-  memcpy (tempstr + 4, &num, 4);
-  if (sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len + 8) < 0)
-    {
-      g_free (tempstr);
-      return (-2);
-    }
-
-  g_free (tempstr);
-  if (request->directory)
-    {
-      g_free (request->directory);
-      request->directory = NULL;
-    }
-
-  memset (&message, 0, sizeof (message));
-  if (sshv2_read_response (request, &message, NULL) != SSH_FXP_NAME)
-    {
-      request->logging_function (gftp_logging_error, request->user_data,
-                     _("Received wrong response from server, disconnecting\n"));
-      sshv2_message_free (&message);
-      gftp_disconnect (request);
-      return (-2);
-    }
-
-  message.pos += 4;
-  if (sshv2_buffer_get_int32 (request, &message, 1) < 0)
-    return (-2);
-
-  if ((request->directory = sshv2_buffer_get_string (request, &message)) == NULL)
-    return (-2);
-  sshv2_message_free (&message);
-  return (0);
-}
-
-
 static int 
 sshv2_rmdir (gftp_request * request, const char *directory)
 {
@@ -1986,3 +1877,50 @@
   return (size);
 }
 
+
+void
+sshv2_init (gftp_request * request)
+{
+  sshv2_params * params;
+
+  g_return_if_fail (request != NULL);
+
+  request->protonum = GFTP_SSHV2_NUM;
+  request->init = sshv2_init;
+  request->destroy = sshv2_destroy;
+  request->connect = sshv2_connect;
+  request->disconnect = sshv2_disconnect;
+  request->get_file = sshv2_get_file;
+  request->put_file = sshv2_put_file;
+  request->transfer_file = NULL;
+  request->get_next_file_chunk = sshv2_get_next_file_chunk;
+  request->put_next_file_chunk = sshv2_put_next_file_chunk;
+  request->end_transfer = sshv2_end_transfer;
+  request->abort_transfer = sshv2_end_transfer; /* NOTE: uses sshv2_end_transfer */
+  request->list_files = sshv2_list_files;
+  request->get_next_file = sshv2_get_next_file;
+  request->set_data_type = NULL;
+  request->get_file_size = sshv2_get_file_size;
+  request->chdir = sshv2_chdir;
+  request->rmdir = sshv2_rmdir;
+  request->rmfile = sshv2_rmfile;
+  request->mkdir = sshv2_mkdir;
+  request->rename = sshv2_rename;
+  request->chmod = sshv2_chmod;
+  request->set_file_time = sshv2_set_file_time;
+  request->site = NULL;
+  request->parse_url = NULL;
+  request->url_prefix = "ssh2";
+  request->protocol_name = "SSH2";
+  request->need_hostport = 1;
+  request->need_userpass = ssh_need_userpass;
+  request->use_cache = 1;
+  request->use_threads = 1;
+  request->always_connected = 0;
+  request->protocol_data = g_malloc0 (sizeof (sshv2_params));
+  gftp_set_config_options (request);
+
+  params = request->protocol_data;
+  params->id = 1;
+}
+
--- a/src/gtk/bookmarks.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/bookmarks.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,39 +20,6 @@
 #include "gftp-gtk.h"
 static const char cvsid[] = "$Id$";
 
-static void doadd_bookmark 			( gpointer * data,
-						  gftp_dialog_data * ddata);
-static void bm_apply_changes 			( GtkWidget * widget, 
-						  gpointer backup_data );
-static gftp_bookmarks * copy_bookmarks 		( gftp_bookmarks * bookmarks );
-static void bm_close_dialog 			( GtkWidget * widget, 
-						  GtkWidget * dialog );
-static void after_move 				( GtkCTree * ctree, 
-						  GtkCTreeNode * child, 
-						  GtkCTreeNode * parent, 
-						  GtkCTreeNode * sibling, 
-						  gpointer data );
-static gint bm_dblclick 			( GtkWidget * widget, 
-						  GdkEventButton * event, 
-						  gpointer data );
-static gint bm_enter 				( GtkWidget * widget, 
-						  GdkEventKey * event, 
-						  gpointer data );
-static void new_folder_entry 			( gpointer data );
-static void do_make_new 			( gpointer data,
-						  gftp_dialog_data * ddata );
-static void new_item_entry 			( gpointer data );
-static void edit_entry 				( gpointer data );
-static void delete_entry 			( gpointer data );
-static void do_delete_entry 			( gftp_bookmarks * entry,
-						  gftp_dialog_data * ddata );
-static void entry_apply_changes 		( GtkWidget * widget, 
-						  gftp_bookmarks * entry );
-static void set_userpass_visible 		( GtkWidget * checkbutton, 
-						  GtkWidget * entry );
-static void build_bookmarks_tree 		( void );
-static void clear_bookmarks_tree 		( void );
-
 static GtkWidget * bm_hostedit, * bm_portedit, * bm_localdiredit,
   * bm_remotediredit, * bm_useredit, * bm_passedit, * bm_acctedit, * anon_chk,
   * bm_pathedit, * bm_protocol, * tree, *bm_sftppath;
@@ -132,25 +99,6 @@
   ftp_connect (current_wdata, current_wdata->request, 1);
 }
 
-void
-add_bookmark (gpointer data)
-{
-  const char *edttxt;
-
-  if (!check_status (_("Add Bookmark"), current_wdata, 0, 0, 0, 1))
-    return;
-
-  edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (hostedit)->entry));
-  if (*edttxt == '\0')
-    {
-      ftp_log (gftp_logging_error, NULL,
-	       _("Add Bookmark: You must enter a hostname\n"));
-      return;
-    }
-
-  MakeEditDialog (_("Add Bookmark"), _("Enter the name of the bookmark you want to add\nYou can separate items by a / to put it into a submenu\n(ex: Linux Sites/Debian)"), NULL, 1, _("Remember password"), gftp_dialog_button_create, doadd_bookmark, data, NULL, NULL);
-}
-
 
 static void
 doadd_bookmark (gpointer * data, gftp_dialog_data * ddata)
@@ -230,6 +178,26 @@
 
 
 void
+add_bookmark (gpointer data)
+{
+  const char *edttxt;
+
+  if (!check_status (_("Add Bookmark"), current_wdata, 0, 0, 0, 1))
+    return;
+
+  edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (hostedit)->entry));
+  if (*edttxt == '\0')
+    {
+      ftp_log (gftp_logging_error, NULL,
+	       _("Add Bookmark: You must enter a hostname\n"));
+      return;
+    }
+
+  MakeEditDialog (_("Add Bookmark"), _("Enter the name of the bookmark you want to add\nYou can separate items by a / to put it into a submenu\n(ex: Linux Sites/Debian)"), NULL, 1, _("Remember password"), gftp_dialog_button_create, doadd_bookmark, data, NULL, NULL);
+}
+
+
+void
 build_bookmarks_menu (void)
 {
   GtkItemFactoryEntry test = { NULL, NULL, NULL, 0 };
@@ -265,132 +233,6 @@
 }
 
 
-#if GTK_MAJOR_VERSION > 1 
-static void
-editbm_action (GtkWidget * widget, gint response, gpointer user_data)
-{
-  switch (response)
-    {
-      case GTK_RESPONSE_OK:
-        bm_apply_changes (widget, NULL);
-        /* no break */
-      default:
-        bm_close_dialog (NULL, widget);
-    }
-}
-#endif
-
-
-void
-edit_bookmarks (gpointer data)
-{
-  GtkWidget * dialog, * scroll;
-  GtkItemFactory * ifactory;
-  GtkItemFactoryEntry menu_items[] = {
-    {N_("/_File"), NULL, 0, 0, "<Branch>"},
-    {N_("/File/tearoff"), NULL, 0, 0, "<Tearoff>"},
-    {N_("/File/New Folder..."), NULL, new_folder_entry, 0, MN_(NULL)},
-    {N_("/File/New Item..."), NULL, new_item_entry, 0, MS_(GTK_STOCK_NEW)},
-    {N_("/File/Delete"), NULL, delete_entry, 0, MS_(GTK_STOCK_DELETE)},
-    {N_("/File/Properties..."), NULL, edit_entry, 0, MS_(GTK_STOCK_PROPERTIES)},
-    {N_("/File/sep"), NULL, 0, 0, "<Separator>"},
-    {N_("/File/Close"), NULL, gtk_widget_destroy, 0, MS_(GTK_STOCK_CLOSE)}
-  };
-#if GTK_MAJOR_VERSION == 1
-  GtkWidget * tempwid;
-#endif
-
-  new_bookmarks = copy_bookmarks (bookmarks);
-  new_bookmarks_htable = build_bookmarks_hash_table (new_bookmarks);
-
-#if GTK_MAJOR_VERSION == 1
-  dialog = gtk_dialog_new ();
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Bookmarks"));
-  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 15);
-#else
-  dialog = gtk_dialog_new_with_buttons (_("Edit Bookmarks"), NULL, 0,
-                                        GTK_STOCK_SAVE,
-                                        GTK_RESPONSE_OK,
-                                        GTK_STOCK_CANCEL,
-                                        GTK_RESPONSE_CANCEL,
-                                        NULL);
-#endif
-  gtk_window_set_wmclass (GTK_WINDOW(dialog), "Edit Bookmarks", "gFTP");
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-  gtk_widget_realize (dialog);
-
-  if (gftp_icon != NULL)
-    {
-      gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
-                           gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
-    }
-
-  /* FIXME - memory leak */
-  ifactory = item_factory_new (GTK_TYPE_MENU_BAR, "<bookmarks>", NULL, NULL);
-  create_item_factory (ifactory, 7, menu_items, NULL);
-  create_item_factory (ifactory, 1, menu_items + 7, dialog);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), ifactory->widget,
-		      FALSE, FALSE, 0);
-  gtk_widget_show (ifactory->widget);
-
-  scroll = gtk_scrolled_window_new (NULL, NULL);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_widget_set_size_request (scroll, 150, 200);
-
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), scroll, TRUE, TRUE,
-		      0);
-  gtk_container_border_width (GTK_CONTAINER (scroll), 3);
-  gtk_widget_show (scroll);
-
-  /* FIXME - memory leak */
-  edit_factory = item_factory_new (GTK_TYPE_MENU, "<edit_bookmark>", NULL, "/File");
-
-  create_item_factory (edit_factory, 6, menu_items + 2, dialog);
-
-  tree = gtk_ctree_new (1, 0);
-  gtk_clist_set_selection_mode (GTK_CLIST (tree), GTK_SELECTION_BROWSE);
-  gtk_clist_set_reorderable (GTK_CLIST (tree), 1);
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll), tree);
-  gtk_signal_connect_after (GTK_OBJECT (tree), "key_press_event",
-			    GTK_SIGNAL_FUNC (bm_enter), (gpointer) tree);
-  gtk_signal_connect_after (GTK_OBJECT (tree), "tree_move",
-			    GTK_SIGNAL_FUNC (after_move), NULL);
-  gtk_signal_connect_after (GTK_OBJECT (tree), "button_press_event",
-			    GTK_SIGNAL_FUNC (bm_dblclick), (gpointer) tree);
-  gtk_widget_show (tree);
-
-#if GTK_MAJOR_VERSION == 1
-  tempwid = gtk_button_new_with_label (_("OK"));
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
-		      TRUE, TRUE, 0);
-  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
-		      GTK_SIGNAL_FUNC (bm_apply_changes), NULL);
-  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
-		      GTK_SIGNAL_FUNC (bm_close_dialog), (gpointer) dialog);
-  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
-  gtk_widget_show (tempwid);
-
-  tempwid = gtk_button_new_with_label (_("  Cancel  "));
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
-		      TRUE, TRUE, 0);
-  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
-		      GTK_SIGNAL_FUNC (bm_close_dialog), (gpointer) dialog);
-  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
-  gtk_widget_grab_focus (tempwid);
-  gtk_widget_show (tempwid);
-#else
-  g_signal_connect (GTK_OBJECT (dialog), "response",
-                    G_CALLBACK (editbm_action), NULL);
-#endif
-
-  gtk_widget_show (dialog);
-
-  build_bookmarks_tree ();
-}
-
-
 static void
 free_bookmark_entry_items (gftp_bookmarks * entry)
 {
@@ -411,87 +253,6 @@
 }
 
 
-static void
-bm_apply_changes (GtkWidget * widget, gpointer backup_data)
-{
-  gftp_bookmarks * tempentry, * delentry;
-  char *tempstr;
-
-  tempentry = bookmarks->children;
-  while (tempentry != NULL)
-    {
-      if (tempentry->path && !tempentry->isfolder)
-	{
-	  tempstr = g_strdup_printf ("/Bookmarks/%s", tempentry->path);
-          gtk_widget_destroy (gtk_item_factory_get_item (factory, tempstr));
-	  g_free (tempentry->path);
-	  g_free (tempstr);
-	}
-
-      free_bookmark_entry_items (tempentry);
-
-      if (tempentry->children != NULL)
-	tempentry = tempentry->children;
-      else
-	{
-	  if (tempentry->next == NULL)
-	    {
-	      while (tempentry->next == NULL && tempentry->prev != NULL)
-		{
-		  delentry = tempentry;
-		  tempentry = tempentry->prev;
-		  if (delentry->isfolder)
-		    {
-		      tempstr = g_strdup_printf ("/Bookmarks/%s", 
-                                                 delentry->path);
-                      gtk_widget_destroy (gtk_item_factory_get_item (factory, 
-                                                                     tempstr));
-		      g_free (tempstr);
-		      g_free (delentry->path);
-		    }
-		  g_free (delentry);
-		}
-	      delentry = tempentry;
-	      tempentry = tempentry->next;
-	      if (delentry->isfolder && tempentry != NULL)
-		{
-		  tempstr = g_strdup_printf ("/Bookmarks/%s", 
-                                             delentry->path);
-                    gtk_widget_destroy (gtk_item_factory_get_item (factory, 
-                                                                   tempstr));
-		  g_free (delentry->path);
-		  g_free (tempstr);
-		  g_free (delentry);
-		}
-	    }
-	  else
-	    {
-	      delentry = tempentry;
-	      tempentry = tempentry->next;
-	      g_free (delentry);
-	    }
-	}
-    }
-  g_free (bookmarks);
-  g_hash_table_destroy (bookmarks_htable);
-
-  bookmarks = new_bookmarks;
-  bookmarks_htable = new_bookmarks_htable;
-  if (backup_data)
-    {
-      new_bookmarks = copy_bookmarks (bookmarks);
-      new_bookmarks_htable = build_bookmarks_hash_table (new_bookmarks);
-    }
-  else
-    {
-      new_bookmarks = NULL;
-      new_bookmarks_htable = NULL;
-    }
-  build_bookmarks_menu ();
-  gftp_write_bookmarks_file ();
-}
-
-
 static gftp_bookmarks *
 copy_bookmarks (gftp_bookmarks * bookmarks)
 {
@@ -605,6 +366,87 @@
 
 
 static void
+bm_apply_changes (GtkWidget * widget, gpointer backup_data)
+{
+  gftp_bookmarks * tempentry, * delentry;
+  char *tempstr;
+
+  tempentry = bookmarks->children;
+  while (tempentry != NULL)
+    {
+      if (tempentry->path && !tempentry->isfolder)
+	{
+	  tempstr = g_strdup_printf ("/Bookmarks/%s", tempentry->path);
+          gtk_widget_destroy (gtk_item_factory_get_item (factory, tempstr));
+	  g_free (tempentry->path);
+	  g_free (tempstr);
+	}
+
+      free_bookmark_entry_items (tempentry);
+
+      if (tempentry->children != NULL)
+	tempentry = tempentry->children;
+      else
+	{
+	  if (tempentry->next == NULL)
+	    {
+	      while (tempentry->next == NULL && tempentry->prev != NULL)
+		{
+		  delentry = tempentry;
+		  tempentry = tempentry->prev;
+		  if (delentry->isfolder)
+		    {
+		      tempstr = g_strdup_printf ("/Bookmarks/%s", 
+                                                 delentry->path);
+                      gtk_widget_destroy (gtk_item_factory_get_item (factory, 
+                                                                     tempstr));
+		      g_free (tempstr);
+		      g_free (delentry->path);
+		    }
+		  g_free (delentry);
+		}
+	      delentry = tempentry;
+	      tempentry = tempentry->next;
+	      if (delentry->isfolder && tempentry != NULL)
+		{
+		  tempstr = g_strdup_printf ("/Bookmarks/%s", 
+                                             delentry->path);
+                    gtk_widget_destroy (gtk_item_factory_get_item (factory, 
+                                                                   tempstr));
+		  g_free (delentry->path);
+		  g_free (tempstr);
+		  g_free (delentry);
+		}
+	    }
+	  else
+	    {
+	      delentry = tempentry;
+	      tempentry = tempentry->next;
+	      g_free (delentry);
+	    }
+	}
+    }
+  g_free (bookmarks);
+  g_hash_table_destroy (bookmarks_htable);
+
+  bookmarks = new_bookmarks;
+  bookmarks_htable = new_bookmarks_htable;
+  if (backup_data)
+    {
+      new_bookmarks = copy_bookmarks (bookmarks);
+      new_bookmarks_htable = build_bookmarks_hash_table (new_bookmarks);
+    }
+  else
+    {
+      new_bookmarks = NULL;
+      new_bookmarks_htable = NULL;
+    }
+  build_bookmarks_menu ();
+  gftp_write_bookmarks_file ();
+}
+
+
+static void
 bm_close_dialog (GtkWidget * widget, GtkWidget * dialog)
 {
   gftp_bookmarks * tempentry, * delentry;
@@ -642,142 +484,20 @@
 }
 
 
+#if GTK_MAJOR_VERSION > 1 
 static void
-after_move (GtkCTree * ctree, GtkCTreeNode * child, GtkCTreeNode * parent,
-	    GtkCTreeNode * sibling, gpointer data)
+editbm_action (GtkWidget * widget, gint response, gpointer user_data)
 {
-
-  gftp_bookmarks * childentry, * siblingentry, * parententry, * tempentry;
-  char *tempstr, *pos, *stpos;
-
-  childentry = gtk_ctree_node_get_row_data (ctree, child);
-  parententry = gtk_ctree_node_get_row_data (ctree, parent);
-  siblingentry = gtk_ctree_node_get_row_data (ctree, sibling);
-
-  tempentry = childentry->prev->children;
-  if (tempentry == childentry)
-    childentry->prev->children = childentry->prev->children->next;
-  else
-    {
-      while (tempentry->next != childentry)
-	tempentry = tempentry->next;
-      tempentry->next = childentry->next;
-    }
-  childentry->prev = parententry;
-  if (!parententry->isfolder)
-    {
-      childentry->next = parententry->children;
-      parententry->children = childentry;
-      gtk_ctree_move (ctree, child, parententry->prev->cnode,
-		      parententry->cnode);
-    }
-  else
+  switch (response)
     {
-      if (siblingentry == NULL || parententry->children == siblingentry)
-	{
-	  childentry->next = parententry->children;
-	  parententry->children = childentry;
-	}
-      else
-	{
-	  tempentry = parententry->children;
-	  while (tempentry->next != siblingentry)
-	    tempentry = tempentry->next;
-	  childentry->next = tempentry->next;
-	  tempentry->next = childentry;
-	}
-
-      tempentry = childentry;
-      while (tempentry != NULL)
-	{
-	  g_hash_table_remove (new_bookmarks_htable, tempentry->path);
-	  if ((pos = strrchr (tempentry->path, '/')) == NULL)
-	    pos = tempentry->path;
-	  else
-	    pos++;
-	  tempstr = g_strdup_printf ("%s/%s", tempentry->prev->path, pos);
-	  for (stpos = tempstr; *stpos == '/'; stpos++);
-	  g_free (tempentry->path);
-	  tempentry->path = g_malloc (strlen (stpos) + 1);
-	  strcpy (tempentry->path, stpos);
-	  g_free (tempstr);
-	  g_hash_table_insert (new_bookmarks_htable, tempentry->path,
-			       tempentry);
-	  if (tempentry->children != NULL)
-	    tempentry = tempentry->children;
-	  else
-	    {
-	      if (tempentry->next == NULL)
-		{
-		  if (tempentry->prev == childentry)
-		    break;
-		  else
-		    {
-		      while (tempentry->next == NULL
-			     && tempentry->prev != NULL)
-			tempentry = tempentry->prev;
-		    }
-		}
-	      tempentry = tempentry->next;
-	    }
-	}
+      case GTK_RESPONSE_OK:
+        bm_apply_changes (widget, NULL);
+        /* no break */
+      default:
+        bm_close_dialog (NULL, widget);
     }
 }
-
-
-static gint
-bm_dblclick (GtkWidget * widget, GdkEventButton * event, gpointer data)
-{
-  if (event->button == 3)
-    gtk_item_factory_popup (edit_factory, (guint) event->x_root,
-			    (guint) event->y_root, 1, 0);
-  else if (event->type == GDK_2BUTTON_PRESS)
-    {
-      edit_entry (NULL);
-      return (FALSE);
-    }
-  return (TRUE);
-}
-
-
-static gint
-bm_enter (GtkWidget * widget, GdkEventKey * event, gpointer data)
-{
-  if (event->type == GDK_KEY_PRESS)
-    {
-      if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)
-	{
-	  edit_entry (NULL);
-	  return (FALSE);
-	}
-      else if (event->keyval == GDK_KP_Delete || event->keyval == GDK_Delete)
-	{
-	  delete_entry (NULL);
-	  return (FALSE);
-	}
-    }
-  return (TRUE);
-}
-
-
-static void
-new_folder_entry (gpointer data)
-{
-  MakeEditDialog (_("New Folder"),
-		  _("Enter the name of the new folder to create"), NULL, 1,
-		  NULL, gftp_dialog_button_create, 
-                  do_make_new, (gpointer) 0x1, NULL, NULL);
-}
-
-
-static void
-new_item_entry (gpointer data)
-{
-  MakeEditDialog (_("New Folder"),
-		  _("Enter the name of the new item to create"), NULL, 1,
-		  NULL, gftp_dialog_button_create,
-                  do_make_new, NULL, NULL, NULL);
-}
+#endif
 
 
 static void
@@ -851,6 +571,353 @@
 }
 
 
+static void
+new_folder_entry (gpointer data)
+{
+  MakeEditDialog (_("New Folder"),
+		  _("Enter the name of the new folder to create"), NULL, 1,
+		  NULL, gftp_dialog_button_create, 
+                  do_make_new, (gpointer) 0x1, NULL, NULL);
+}
+
+
+static void
+new_item_entry (gpointer data)
+{
+  MakeEditDialog (_("New Folder"),
+		  _("Enter the name of the new item to create"), NULL, 1,
+		  NULL, gftp_dialog_button_create,
+                  do_make_new, NULL, NULL, NULL);
+}
+
+
+static void
+do_delete_entry (gftp_bookmarks * entry, gftp_dialog_data * ddata)
+{
+  gftp_bookmarks * tempentry, * delentry;
+
+  g_hash_table_remove (new_bookmarks_htable, entry->path);
+  gtk_ctree_remove_node (GTK_CTREE (tree), entry->cnode);
+  if (entry->prev->children == entry)
+    entry->prev->children = entry->prev->children->next;
+  else
+    {
+      tempentry = entry->prev->children;
+      while (tempentry->next != entry)
+	tempentry = tempentry->next;
+      tempentry->next = entry->next;
+    }
+
+  entry->prev = NULL;
+  entry->next = NULL;
+  tempentry = entry;
+  while (tempentry != NULL)
+    {
+      if (tempentry->path)
+	g_free (tempentry->path);
+      if (tempentry->hostname)
+	g_free (tempentry->hostname);
+      if (tempentry->remote_dir)
+	g_free (tempentry->remote_dir);
+      if (tempentry->user)
+	g_free (tempentry->user);
+      if (tempentry->pass)
+	g_free (tempentry->pass);
+      if (tempentry->sftpserv_path)
+        g_free (tempentry->sftpserv_path);
+
+      if (tempentry->children != NULL)
+	{
+	  tempentry = tempentry->children;
+	  continue;
+	}
+      else if (tempentry->next == NULL && tempentry->prev != NULL)
+	{
+	  delentry = tempentry->prev;
+	  g_free (tempentry);
+	  tempentry = delentry->next;
+	  if (delentry != entry)
+	    g_free (delentry);
+	}
+      else
+	tempentry = tempentry->next;
+    }
+  g_free (entry);
+}
+
+
+static void
+delete_entry (gpointer data)
+{
+  gftp_bookmarks * entry;
+  char *tempstr, *pos;
+
+  if (GTK_CLIST (tree)->selection == NULL)
+    return;
+  entry =
+    gtk_ctree_node_get_row_data (GTK_CTREE (tree),
+				 GTK_CLIST (tree)->selection->data);
+  if (entry == NULL || entry->prev == NULL)
+    return;
+
+  if (!entry->isfolder)
+    do_delete_entry (entry, NULL);
+  else
+    {
+      if ((pos = strrchr (entry->path, '/')) == NULL)
+	pos = entry->path;
+      else
+	pos++;
+
+      tempstr = g_strdup_printf (_("Are you sure you want to erase the bookmark\n%s and all it's children?"), pos);
+      MakeYesNoDialog (_("Delete Bookmark"), tempstr, do_delete_entry, entry, 
+                       NULL, NULL);
+      g_free (tempstr);
+    }
+}
+
+
+static void
+set_userpass_visible (GtkWidget * checkbutton, GtkWidget * entry)
+{
+  gtk_widget_set_sensitive (bm_useredit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
+  gtk_widget_set_sensitive (bm_passedit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
+  gtk_widget_set_sensitive (bm_acctedit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
+}
+
+
+static void
+build_bookmarks_tree (void)
+{
+  GdkPixmap * closedir_pixmap, * opendir_pixmap;
+  GdkBitmap * closedir_bitmap, * opendir_bitmap;  
+  gftp_bookmarks * tempentry, * preventry;
+  char *pos, *prevpos, *text[2], *str;
+  GtkCTreeNode * parent;
+
+  gftp_get_pixmap (tree, "open_dir.xpm", &opendir_pixmap, &opendir_bitmap);
+  gftp_get_pixmap (tree, "dir.xpm", &closedir_pixmap, &closedir_bitmap);
+  text[0] = text[1] = _("Bookmarks");
+  parent = gtk_ctree_insert_node (GTK_CTREE (tree), NULL, NULL, text, 5, 
+                                  closedir_pixmap, closedir_bitmap, 
+                                  opendir_pixmap, opendir_bitmap, FALSE, TRUE);
+  gtk_ctree_node_set_row_data (GTK_CTREE (tree), parent, new_bookmarks);
+  new_bookmarks->cnode = parent;
+
+  tempentry = new_bookmarks->children;
+  while (tempentry != NULL)
+    {
+      tempentry->cnode = NULL;
+      if (tempentry->children != NULL)
+	{
+	  tempentry = tempentry->children;
+	  continue;
+	}
+      else
+	{
+	  pos = tempentry->path;
+	  while ((pos = strchr (pos, '/')) != NULL)
+	    {
+	      *pos = '\0';
+	      str = g_malloc (strlen (tempentry->path) + 1);
+	      strcpy (str, tempentry->path);
+	      *pos = '/';
+	      preventry = g_hash_table_lookup (new_bookmarks_htable, str);
+	      if (preventry->cnode == NULL)
+		{
+		  if ((prevpos = strrchr (str, '/')) == NULL)
+		    prevpos = str;
+		  else
+		    prevpos++;
+		  text[0] = text[1] = prevpos;
+		  preventry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree),
+					   preventry->prev->cnode, NULL, text,
+					   5, closedir_pixmap, closedir_bitmap,
+					   opendir_pixmap, opendir_bitmap,
+					   FALSE, FALSE);
+		  gtk_ctree_node_set_row_data (GTK_CTREE (tree),
+					       preventry->cnode, preventry);
+		}
+
+	      g_free (str);
+	      pos++;
+	    }
+	}
+
+      if ((pos = strrchr (tempentry->path, '/')) == NULL)
+	pos = tempentry->path;
+      else
+	pos++;
+
+      text[0] = text[1] = pos;
+      tempentry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree), 
+                               tempentry->prev->cnode, NULL,
+			       text, 5, NULL, NULL, NULL, NULL, FALSE, FALSE);
+      gtk_ctree_node_set_row_data (GTK_CTREE (tree), tempentry->cnode,
+				   tempentry);
+
+      while (tempentry->next == NULL && tempentry->prev != NULL)
+	tempentry = tempentry->prev;
+      tempentry = tempentry->next;
+    }
+}
+
+
+static void
+clear_bookmarks_tree (void)
+{
+  gftp_bookmarks * tempentry;
+
+  tempentry = new_bookmarks->children;
+  while (tempentry != NULL)
+    {
+      if (tempentry->children != NULL)
+	{
+	  tempentry = tempentry->children;
+	  continue;
+	}
+      while (tempentry->next == NULL && tempentry->prev != NULL)
+	{
+	  gtk_ctree_remove_node (GTK_CTREE (tree), tempentry->cnode);
+	  tempentry->cnode = NULL;
+	  tempentry = tempentry->prev;
+	}
+      gtk_ctree_remove_node (GTK_CTREE (tree), tempentry->cnode);
+      tempentry->cnode = NULL;
+      tempentry = tempentry->next;
+    }
+}
+
+
+static void
+entry_apply_changes (GtkWidget * widget, gftp_bookmarks * entry)
+{
+  char *pos, *newpath, tempchar, *tempstr, *origpath;
+  gftp_bookmarks * tempentry, * nextentry;
+  GtkWidget * tempwid;
+  const char *str;
+  int oldpathlen;
+
+  oldpathlen = strlen (entry->path);
+  if ((pos = strrchr (entry->path, '/')) == NULL)
+    {
+      pos = entry->path;
+      tempchar = *entry->path;
+      *entry->path = '\0';
+    }
+  else
+    {
+      tempchar = *pos;
+      *pos = '\0';
+    }
+  origpath = newpath = g_strconcat (entry->path, "/",
+                         gtk_entry_get_text (GTK_ENTRY (bm_pathedit)), NULL);
+  remove_double_slashes (newpath);
+  for (; *newpath == '/'; newpath++);
+  *pos = tempchar;
+
+  str = gtk_entry_get_text (GTK_ENTRY (bm_hostedit));
+  if (entry->hostname)
+    g_free (entry->hostname);
+  entry->hostname = g_malloc (strlen (str) + 1);
+  strcpy (entry->hostname, str);
+
+  str = gtk_entry_get_text (GTK_ENTRY (bm_portedit));
+  entry->port = strtol (str, NULL, 10);
+
+  tempwid = gtk_menu_get_active (GTK_MENU (bm_protocol));
+  str = gtk_object_get_user_data (GTK_OBJECT (tempwid));
+  if (entry->protocol)
+    g_free (entry->protocol);
+  entry->protocol = g_malloc (strlen (str) + 1);
+  strcpy (entry->protocol, str);
+
+  str = gtk_entry_get_text (GTK_ENTRY (bm_remotediredit));
+  if (entry->remote_dir)
+    g_free (entry->remote_dir);
+  entry->remote_dir = g_malloc (strlen (str) + 1);
+  strcpy (entry->remote_dir, str);
+
+  str = gtk_entry_get_text (GTK_ENTRY (bm_localdiredit));
+  if (entry->local_dir)
+    g_free (entry->local_dir);
+  entry->local_dir = g_malloc (strlen (str) + 1);
+  strcpy (entry->local_dir, str);
+
+  str = gtk_entry_get_text (GTK_ENTRY (bm_sftppath));
+  if (entry->sftpserv_path)
+    g_free (entry->sftpserv_path);
+  if (strlen (str) > 0)
+    {
+      entry->sftpserv_path = g_malloc (strlen (str) + 1);
+      strcpy (entry->sftpserv_path, str);
+    }
+  else
+    entry->sftpserv_path = NULL;
+
+  if (GTK_TOGGLE_BUTTON (anon_chk)->active)
+    str = "anonymous";
+  else
+    str = gtk_entry_get_text (GTK_ENTRY (bm_useredit));
+  if (entry->user)
+    g_free (entry->user);
+  entry->user = g_malloc (strlen (str) + 1);
+  strcpy (entry->user, str);
+
+  if (GTK_TOGGLE_BUTTON (anon_chk)->active)
+    str = "@EMAIL@";
+  else
+    str = gtk_entry_get_text (GTK_ENTRY (bm_passedit));
+  if (entry->pass)
+    g_free (entry->pass);
+  entry->pass = g_malloc (strlen (str) + 1);
+  strcpy (entry->pass, str);
+  entry->save_password = *entry->pass != '\0';
+
+  if (GTK_TOGGLE_BUTTON (anon_chk)->active)
+    str = "";
+  else
+    str = gtk_entry_get_text (GTK_ENTRY (bm_acctedit));
+  if (entry->acct)
+    g_free (entry->acct);
+  entry->acct = g_malloc (strlen (str) + 1);
+  strcpy (entry->acct, str);
+
+  if (strcmp (entry->path, newpath) != 0)
+    {
+      tempentry = entry;
+      nextentry = entry->next;
+      entry->next = NULL;
+      while (tempentry != NULL)
+	{
+	  g_hash_table_remove (new_bookmarks_htable, tempentry->path);
+	  tempstr = g_strconcat (newpath, "/", tempentry->path + oldpathlen, 
+                                 NULL);
+	  remove_double_slashes (tempstr);
+	  g_free (tempentry->path);
+	  tempentry->path = tempstr;
+	  g_hash_table_insert (new_bookmarks_htable, tempentry->path,
+			       tempentry);
+	  if (tempentry->children != NULL)
+	    {
+	      tempentry = tempentry->children;
+	      continue;
+	    }
+	  while (tempentry->next == NULL && tempentry != entry &&
+		 tempentry->prev != NULL)
+	    tempentry = tempentry->prev;
+
+	  tempentry = tempentry->next;
+	}
+      entry->next = nextentry;
+      clear_bookmarks_tree ();
+      build_bookmarks_tree ();
+    }
+
+  g_free (origpath);
+}
+
+
 #if GTK_MAJOR_VERSION > 1
 static void
 bmedit_action (GtkWidget * widget, gint response, gpointer user_data)
@@ -1131,329 +1198,230 @@
 }
 
 
-static void
-delete_entry (gpointer data)
+static gint
+bm_enter (GtkWidget * widget, GdkEventKey * event, gpointer data)
 {
-  gftp_bookmarks * entry;
-  char *tempstr, *pos;
-
-  if (GTK_CLIST (tree)->selection == NULL)
-    return;
-  entry =
-    gtk_ctree_node_get_row_data (GTK_CTREE (tree),
-				 GTK_CLIST (tree)->selection->data);
-  if (entry == NULL || entry->prev == NULL)
-    return;
-
-  if (!entry->isfolder)
-    do_delete_entry (entry, NULL);
-  else
-    {
-      if ((pos = strrchr (entry->path, '/')) == NULL)
-	pos = entry->path;
-      else
-	pos++;
-
-      tempstr = g_strdup_printf (_("Are you sure you want to erase the bookmark\n%s and all it's children?"), pos);
-      MakeYesNoDialog (_("Delete Bookmark"), tempstr, do_delete_entry, entry, 
-                       NULL, NULL);
-      g_free (tempstr);
-    }
-}
-
-
-static void
-do_delete_entry (gftp_bookmarks * entry, gftp_dialog_data * ddata)
-{
-  gftp_bookmarks * tempentry, * delentry;
-
-  g_hash_table_remove (new_bookmarks_htable, entry->path);
-  gtk_ctree_remove_node (GTK_CTREE (tree), entry->cnode);
-  if (entry->prev->children == entry)
-    entry->prev->children = entry->prev->children->next;
-  else
+  if (event->type == GDK_KEY_PRESS)
     {
-      tempentry = entry->prev->children;
-      while (tempentry->next != entry)
-	tempentry = tempentry->next;
-      tempentry->next = entry->next;
+      if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)
+	{
+	  edit_entry (NULL);
+	  return (FALSE);
+	}
+      else if (event->keyval == GDK_KP_Delete || event->keyval == GDK_Delete)
+	{
+	  delete_entry (NULL);
+	  return (FALSE);
+	}
     }
-
-  entry->prev = NULL;
-  entry->next = NULL;
-  tempentry = entry;
-  while (tempentry != NULL)
-    {
-      if (tempentry->path)
-	g_free (tempentry->path);
-      if (tempentry->hostname)
-	g_free (tempentry->hostname);
-      if (tempentry->remote_dir)
-	g_free (tempentry->remote_dir);
-      if (tempentry->user)
-	g_free (tempentry->user);
-      if (tempentry->pass)
-	g_free (tempentry->pass);
-      if (tempentry->sftpserv_path)
-        g_free (tempentry->sftpserv_path);
-
-      if (tempentry->children != NULL)
-	{
-	  tempentry = tempentry->children;
-	  continue;
-	}
-      else if (tempentry->next == NULL && tempentry->prev != NULL)
-	{
-	  delentry = tempentry->prev;
-	  g_free (tempentry);
-	  tempentry = delentry->next;
-	  if (delentry != entry)
-	    g_free (delentry);
-	}
-      else
-	tempentry = tempentry->next;
-    }
-  g_free (entry);
+  return (TRUE);
 }
 
 
 static void
-entry_apply_changes (GtkWidget * widget, gftp_bookmarks * entry)
+after_move (GtkCTree * ctree, GtkCTreeNode * child, GtkCTreeNode * parent,
+	    GtkCTreeNode * sibling, gpointer data)
 {
-  char *pos, *newpath, tempchar, *tempstr, *origpath;
-  gftp_bookmarks * tempentry, * nextentry;
-  GtkWidget * tempwid;
-  const char *str;
-  int oldpathlen;
+
+  gftp_bookmarks * childentry, * siblingentry, * parententry, * tempentry;
+  char *tempstr, *pos, *stpos;
+
+  childentry = gtk_ctree_node_get_row_data (ctree, child);
+  parententry = gtk_ctree_node_get_row_data (ctree, parent);
+  siblingentry = gtk_ctree_node_get_row_data (ctree, sibling);
 
-  oldpathlen = strlen (entry->path);
-  if ((pos = strrchr (entry->path, '/')) == NULL)
+  tempentry = childentry->prev->children;
+  if (tempentry == childentry)
+    childentry->prev->children = childentry->prev->children->next;
+  else
     {
-      pos = entry->path;
-      tempchar = *entry->path;
-      *entry->path = '\0';
+      while (tempentry->next != childentry)
+	tempentry = tempentry->next;
+      tempentry->next = childentry->next;
+    }
+  childentry->prev = parententry;
+  if (!parententry->isfolder)
+    {
+      childentry->next = parententry->children;
+      parententry->children = childentry;
+      gtk_ctree_move (ctree, child, parententry->prev->cnode,
+		      parententry->cnode);
     }
   else
     {
-      tempchar = *pos;
-      *pos = '\0';
-    }
-  origpath = newpath = g_strconcat (entry->path, "/",
-                         gtk_entry_get_text (GTK_ENTRY (bm_pathedit)), NULL);
-  remove_double_slashes (newpath);
-  for (; *newpath == '/'; newpath++);
-  *pos = tempchar;
-
-  str = gtk_entry_get_text (GTK_ENTRY (bm_hostedit));
-  if (entry->hostname)
-    g_free (entry->hostname);
-  entry->hostname = g_malloc (strlen (str) + 1);
-  strcpy (entry->hostname, str);
-
-  str = gtk_entry_get_text (GTK_ENTRY (bm_portedit));
-  entry->port = strtol (str, NULL, 10);
-
-  tempwid = gtk_menu_get_active (GTK_MENU (bm_protocol));
-  str = gtk_object_get_user_data (GTK_OBJECT (tempwid));
-  if (entry->protocol)
-    g_free (entry->protocol);
-  entry->protocol = g_malloc (strlen (str) + 1);
-  strcpy (entry->protocol, str);
-
-  str = gtk_entry_get_text (GTK_ENTRY (bm_remotediredit));
-  if (entry->remote_dir)
-    g_free (entry->remote_dir);
-  entry->remote_dir = g_malloc (strlen (str) + 1);
-  strcpy (entry->remote_dir, str);
-
-  str = gtk_entry_get_text (GTK_ENTRY (bm_localdiredit));
-  if (entry->local_dir)
-    g_free (entry->local_dir);
-  entry->local_dir = g_malloc (strlen (str) + 1);
-  strcpy (entry->local_dir, str);
+      if (siblingentry == NULL || parententry->children == siblingentry)
+	{
+	  childentry->next = parententry->children;
+	  parententry->children = childentry;
+	}
+      else
+	{
+	  tempentry = parententry->children;
+	  while (tempentry->next != siblingentry)
+	    tempentry = tempentry->next;
+	  childentry->next = tempentry->next;
+	  tempentry->next = childentry;
+	}
 
-  str = gtk_entry_get_text (GTK_ENTRY (bm_sftppath));
-  if (entry->sftpserv_path)
-    g_free (entry->sftpserv_path);
-  if (strlen (str) > 0)
-    {
-      entry->sftpserv_path = g_malloc (strlen (str) + 1);
-      strcpy (entry->sftpserv_path, str);
-    }
-  else
-    entry->sftpserv_path = NULL;
-
-  if (GTK_TOGGLE_BUTTON (anon_chk)->active)
-    str = "anonymous";
-  else
-    str = gtk_entry_get_text (GTK_ENTRY (bm_useredit));
-  if (entry->user)
-    g_free (entry->user);
-  entry->user = g_malloc (strlen (str) + 1);
-  strcpy (entry->user, str);
-
-  if (GTK_TOGGLE_BUTTON (anon_chk)->active)
-    str = "@EMAIL@";
-  else
-    str = gtk_entry_get_text (GTK_ENTRY (bm_passedit));
-  if (entry->pass)
-    g_free (entry->pass);
-  entry->pass = g_malloc (strlen (str) + 1);
-  strcpy (entry->pass, str);
-  entry->save_password = *entry->pass != '\0';
-
-  if (GTK_TOGGLE_BUTTON (anon_chk)->active)
-    str = "";
-  else
-    str = gtk_entry_get_text (GTK_ENTRY (bm_acctedit));
-  if (entry->acct)
-    g_free (entry->acct);
-  entry->acct = g_malloc (strlen (str) + 1);
-  strcpy (entry->acct, str);
-
-  if (strcmp (entry->path, newpath) != 0)
-    {
-      tempentry = entry;
-      nextentry = entry->next;
-      entry->next = NULL;
+      tempentry = childentry;
       while (tempentry != NULL)
 	{
 	  g_hash_table_remove (new_bookmarks_htable, tempentry->path);
-	  tempstr = g_strconcat (newpath, "/", tempentry->path + oldpathlen, 
-                                 NULL);
-	  remove_double_slashes (tempstr);
+	  if ((pos = strrchr (tempentry->path, '/')) == NULL)
+	    pos = tempentry->path;
+	  else
+	    pos++;
+	  tempstr = g_strdup_printf ("%s/%s", tempentry->prev->path, pos);
+	  for (stpos = tempstr; *stpos == '/'; stpos++);
 	  g_free (tempentry->path);
-	  tempentry->path = tempstr;
+	  tempentry->path = g_malloc (strlen (stpos) + 1);
+	  strcpy (tempentry->path, stpos);
+	  g_free (tempstr);
 	  g_hash_table_insert (new_bookmarks_htable, tempentry->path,
 			       tempentry);
 	  if (tempentry->children != NULL)
+	    tempentry = tempentry->children;
+	  else
 	    {
-	      tempentry = tempentry->children;
-	      continue;
-	    }
-	  while (tempentry->next == NULL && tempentry != entry &&
-		 tempentry->prev != NULL)
-	    tempentry = tempentry->prev;
-
-	  tempentry = tempentry->next;
-	}
-      entry->next = nextentry;
-      clear_bookmarks_tree ();
-      build_bookmarks_tree ();
-    }
-
-  g_free (origpath);
-}
-
-
-static void
-set_userpass_visible (GtkWidget * checkbutton, GtkWidget * entry)
-{
-  gtk_widget_set_sensitive (bm_useredit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
-  gtk_widget_set_sensitive (bm_passedit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
-  gtk_widget_set_sensitive (bm_acctedit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
-}
-
-
-static void
-build_bookmarks_tree (void)
-{
-  GdkPixmap * closedir_pixmap, * opendir_pixmap;
-  GdkBitmap * closedir_bitmap, * opendir_bitmap;  
-  gftp_bookmarks * tempentry, * preventry;
-  char *pos, *prevpos, *text[2], *str;
-  GtkCTreeNode * parent;
-
-  gftp_get_pixmap (tree, "open_dir.xpm", &opendir_pixmap, &opendir_bitmap);
-  gftp_get_pixmap (tree, "dir.xpm", &closedir_pixmap, &closedir_bitmap);
-  text[0] = text[1] = _("Bookmarks");
-  parent = gtk_ctree_insert_node (GTK_CTREE (tree), NULL, NULL, text, 5, 
-                                  closedir_pixmap, closedir_bitmap, 
-                                  opendir_pixmap, opendir_bitmap, FALSE, TRUE);
-  gtk_ctree_node_set_row_data (GTK_CTREE (tree), parent, new_bookmarks);
-  new_bookmarks->cnode = parent;
-
-  tempentry = new_bookmarks->children;
-  while (tempentry != NULL)
-    {
-      tempentry->cnode = NULL;
-      if (tempentry->children != NULL)
-	{
-	  tempentry = tempentry->children;
-	  continue;
-	}
-      else
-	{
-	  pos = tempentry->path;
-	  while ((pos = strchr (pos, '/')) != NULL)
-	    {
-	      *pos = '\0';
-	      str = g_malloc (strlen (tempentry->path) + 1);
-	      strcpy (str, tempentry->path);
-	      *pos = '/';
-	      preventry = g_hash_table_lookup (new_bookmarks_htable, str);
-	      if (preventry->cnode == NULL)
+	      if (tempentry->next == NULL)
 		{
-		  if ((prevpos = strrchr (str, '/')) == NULL)
-		    prevpos = str;
+		  if (tempentry->prev == childentry)
+		    break;
 		  else
-		    prevpos++;
-		  text[0] = text[1] = prevpos;
-		  preventry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree),
-					   preventry->prev->cnode, NULL, text,
-					   5, closedir_pixmap, closedir_bitmap,
-					   opendir_pixmap, opendir_bitmap,
-					   FALSE, FALSE);
-		  gtk_ctree_node_set_row_data (GTK_CTREE (tree),
-					       preventry->cnode, preventry);
+		    {
+		      while (tempentry->next == NULL
+			     && tempentry->prev != NULL)
+			tempentry = tempentry->prev;
+		    }
 		}
-
-	      g_free (str);
-	      pos++;
+	      tempentry = tempentry->next;
 	    }
 	}
-
-      if ((pos = strrchr (tempentry->path, '/')) == NULL)
-	pos = tempentry->path;
-      else
-	pos++;
-
-      text[0] = text[1] = pos;
-      tempentry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree), 
-                               tempentry->prev->cnode, NULL,
-			       text, 5, NULL, NULL, NULL, NULL, FALSE, FALSE);
-      gtk_ctree_node_set_row_data (GTK_CTREE (tree), tempentry->cnode,
-				   tempentry);
-
-      while (tempentry->next == NULL && tempentry->prev != NULL)
-	tempentry = tempentry->prev;
-      tempentry = tempentry->next;
     }
 }
 
 
-static void
-clear_bookmarks_tree (void)
+static gint
+bm_dblclick (GtkWidget * widget, GdkEventButton * event, gpointer data)
 {
-  gftp_bookmarks * tempentry;
-
-  tempentry = new_bookmarks->children;
-  while (tempentry != NULL)
+  if (event->button == 3)
+    gtk_item_factory_popup (edit_factory, (guint) event->x_root,
+			    (guint) event->y_root, 1, 0);
+  else if (event->type == GDK_2BUTTON_PRESS)
     {
-      if (tempentry->children != NULL)
-	{
-	  tempentry = tempentry->children;
-	  continue;
-	}
-      while (tempentry->next == NULL && tempentry->prev != NULL)
-	{
-	  gtk_ctree_remove_node (GTK_CTREE (tree), tempentry->cnode);
-	  tempentry->cnode = NULL;
-	  tempentry = tempentry->prev;
-	}
-      gtk_ctree_remove_node (GTK_CTREE (tree), tempentry->cnode);
-      tempentry->cnode = NULL;
-      tempentry = tempentry->next;
+      edit_entry (NULL);
+      return (FALSE);
     }
+  return (TRUE);
 }
 
+
+void
+edit_bookmarks (gpointer data)
+{
+  GtkWidget * dialog, * scroll;
+  GtkItemFactory * ifactory;
+  GtkItemFactoryEntry menu_items[] = {
+    {N_("/_File"), NULL, 0, 0, "<Branch>"},
+    {N_("/File/tearoff"), NULL, 0, 0, "<Tearoff>"},
+    {N_("/File/New Folder..."), NULL, new_folder_entry, 0, MN_(NULL)},
+    {N_("/File/New Item..."), NULL, new_item_entry, 0, MS_(GTK_STOCK_NEW)},
+    {N_("/File/Delete"), NULL, delete_entry, 0, MS_(GTK_STOCK_DELETE)},
+    {N_("/File/Properties..."), NULL, edit_entry, 0, MS_(GTK_STOCK_PROPERTIES)},
+    {N_("/File/sep"), NULL, 0, 0, "<Separator>"},
+    {N_("/File/Close"), NULL, gtk_widget_destroy, 0, MS_(GTK_STOCK_CLOSE)}
+  };
+#if GTK_MAJOR_VERSION == 1
+  GtkWidget * tempwid;
+#endif
+
+  new_bookmarks = copy_bookmarks (bookmarks);
+  new_bookmarks_htable = build_bookmarks_hash_table (new_bookmarks);
+
+#if GTK_MAJOR_VERSION == 1
+  dialog = gtk_dialog_new ();
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Bookmarks"));
+  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 15);
+#else
+  dialog = gtk_dialog_new_with_buttons (_("Edit Bookmarks"), NULL, 0,
+                                        GTK_STOCK_SAVE,
+                                        GTK_RESPONSE_OK,
+                                        GTK_STOCK_CANCEL,
+                                        GTK_RESPONSE_CANCEL,
+                                        NULL);
+#endif
+  gtk_window_set_wmclass (GTK_WINDOW(dialog), "Edit Bookmarks", "gFTP");
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+  gtk_widget_realize (dialog);
+
+  if (gftp_icon != NULL)
+    {
+      gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
+                           gftp_icon->bitmap);
+      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+    }
+
+  /* FIXME - memory leak */
+  ifactory = item_factory_new (GTK_TYPE_MENU_BAR, "<bookmarks>", NULL, NULL);
+  create_item_factory (ifactory, 7, menu_items, NULL);
+  create_item_factory (ifactory, 1, menu_items + 7, dialog);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), ifactory->widget,
+		      FALSE, FALSE, 0);
+  gtk_widget_show (ifactory->widget);
+
+  scroll = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_widget_set_size_request (scroll, 150, 200);
+
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), scroll, TRUE, TRUE,
+		      0);
+  gtk_container_border_width (GTK_CONTAINER (scroll), 3);
+  gtk_widget_show (scroll);
+
+  /* FIXME - memory leak */
+  edit_factory = item_factory_new (GTK_TYPE_MENU, "<edit_bookmark>", NULL, "/File");
+
+  create_item_factory (edit_factory, 6, menu_items + 2, dialog);
+
+  tree = gtk_ctree_new (1, 0);
+  gtk_clist_set_selection_mode (GTK_CLIST (tree), GTK_SELECTION_BROWSE);
+  gtk_clist_set_reorderable (GTK_CLIST (tree), 1);
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll), tree);
+  gtk_signal_connect_after (GTK_OBJECT (tree), "key_press_event",
+			    GTK_SIGNAL_FUNC (bm_enter), (gpointer) tree);
+  gtk_signal_connect_after (GTK_OBJECT (tree), "tree_move",
+			    GTK_SIGNAL_FUNC (after_move), NULL);
+  gtk_signal_connect_after (GTK_OBJECT (tree), "button_press_event",
+			    GTK_SIGNAL_FUNC (bm_dblclick), (gpointer) tree);
+  gtk_widget_show (tree);
+
+#if GTK_MAJOR_VERSION == 1
+  tempwid = gtk_button_new_with_label (_("OK"));
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
+		      TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
+		      GTK_SIGNAL_FUNC (bm_apply_changes), NULL);
+  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
+		      GTK_SIGNAL_FUNC (bm_close_dialog), (gpointer) dialog);
+  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
+  gtk_widget_show (tempwid);
+
+  tempwid = gtk_button_new_with_label (_("  Cancel  "));
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
+		      TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
+		      GTK_SIGNAL_FUNC (bm_close_dialog), (gpointer) dialog);
+  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
+  gtk_widget_grab_focus (tempwid);
+  gtk_widget_show (tempwid);
+#else
+  g_signal_connect (GTK_OBJECT (dialog), "response",
+                    G_CALLBACK (editbm_action), NULL);
+#endif
+
+  gtk_widget_show (dialog);
+
+  build_bookmarks_tree ();
+}
+
--- a/src/gtk/chmod_dialog.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/chmod_dialog.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,14 +20,114 @@
 #include "gftp-gtk.h"
 static const char cvsid[] = "$Id$";
 
-static void dochmod 				( GtkWidget * widget, 
-						  gftp_window_data * wdata );
-static void *do_chmod_thread 			( void * data );
-
 static GtkWidget *suid, *sgid, *sticky, *ur, *uw, *ux, *gr, *gw, *gx, *or, *ow,
                  *ox;
 static int mode; 
 
+
+static void *
+do_chmod_thread (void * data)
+{
+  GList * filelist, * templist;
+  gftp_window_data * wdata;
+  int success, num, sj;
+  gftp_file * tempfle;
+
+  wdata = data;
+  wdata->request->user_data = (void *) 0x01;
+
+  if (wdata->request->use_threads)
+    {
+      sj = sigsetjmp (jmp_environment, 1);
+      use_jmp_environment = 1;
+    }
+  else
+    sj = 0;
+
+  success = 0;
+  if (sj == 0)
+    { 
+      filelist = wdata->files;
+      templist = GTK_CLIST (wdata->listbox)->selection;
+      num = 0;
+      while (templist != NULL)
+        {
+          templist = get_next_selection (templist, &filelist, &num);
+          tempfle = filelist->data;
+          if (wdata->request->network_timeout > 0)
+            alarm (wdata->request->network_timeout);
+          if (gftp_chmod (wdata->request, tempfle->file, mode) == 0)
+            success = 1;
+          if (!GFTP_IS_CONNECTED (wdata->request))
+            break;
+        }
+      alarm (0);
+    }
+  else
+    {
+      gftp_disconnect (wdata->request);
+      wdata->request->logging_function (gftp_logging_error, 
+                                        wdata->request->user_data,
+                                        _("Operation canceled\n"));
+    }
+
+  if (wdata->request->use_threads)
+    use_jmp_environment = 0;
+
+  wdata->request->user_data = NULL;
+  wdata->request->stopable = 0;
+  return ((void *) success);
+}
+
+
+static void
+dochmod (GtkWidget * widget, gftp_window_data * wdata)
+{
+  int cur;
+
+  mode = 0;
+  if (GTK_TOGGLE_BUTTON (suid)->active)
+    mode += 4;
+  if (GTK_TOGGLE_BUTTON (sgid)->active)
+    mode += 2;
+  if (GTK_TOGGLE_BUTTON (sticky)->active)
+    mode += 1;
+
+  cur = 0;
+  if (GTK_TOGGLE_BUTTON (ur)->active)
+    cur += 4;
+  if (GTK_TOGGLE_BUTTON (uw)->active)
+    cur += 2;
+  if (GTK_TOGGLE_BUTTON (ux)->active)
+    cur += 1;
+  mode = mode * 10 + cur;
+
+  cur = 0;
+  if (GTK_TOGGLE_BUTTON (gr)->active)
+    cur += 4;
+  if (GTK_TOGGLE_BUTTON (gw)->active)
+    cur += 2;
+  if (GTK_TOGGLE_BUTTON (gx)->active)
+    cur += 1;
+  mode = mode * 10 + cur;
+
+  cur = 0;
+  if (GTK_TOGGLE_BUTTON (or)->active)
+    cur += 4;
+  if (GTK_TOGGLE_BUTTON (ow)->active)
+    cur += 2;
+  if (GTK_TOGGLE_BUTTON (ox)->active)
+    cur += 1;
+  mode = mode * 10 + cur;
+
+  if (check_reconnect (wdata) < 0)
+    return;
+
+   if ((int) generic_thread (do_chmod_thread, wdata))
+    refresh (wdata);
+}
+
+
 #if GTK_MAJOR_VERSION > 1
 static void
 chmod_action (GtkWidget * widget, gint response, gpointer wdata)
@@ -239,106 +339,3 @@
   gtk_widget_show (dialog);
 }
 
-
-static void
-dochmod (GtkWidget * widget, gftp_window_data * wdata)
-{
-  int cur;
-
-  mode = 0;
-  if (GTK_TOGGLE_BUTTON (suid)->active)
-    mode += 4;
-  if (GTK_TOGGLE_BUTTON (sgid)->active)
-    mode += 2;
-  if (GTK_TOGGLE_BUTTON (sticky)->active)
-    mode += 1;
-
-  cur = 0;
-  if (GTK_TOGGLE_BUTTON (ur)->active)
-    cur += 4;
-  if (GTK_TOGGLE_BUTTON (uw)->active)
-    cur += 2;
-  if (GTK_TOGGLE_BUTTON (ux)->active)
-    cur += 1;
-  mode = mode * 10 + cur;
-
-  cur = 0;
-  if (GTK_TOGGLE_BUTTON (gr)->active)
-    cur += 4;
-  if (GTK_TOGGLE_BUTTON (gw)->active)
-    cur += 2;
-  if (GTK_TOGGLE_BUTTON (gx)->active)
-    cur += 1;
-  mode = mode * 10 + cur;
-
-  cur = 0;
-  if (GTK_TOGGLE_BUTTON (or)->active)
-    cur += 4;
-  if (GTK_TOGGLE_BUTTON (ow)->active)
-    cur += 2;
-  if (GTK_TOGGLE_BUTTON (ox)->active)
-    cur += 1;
-  mode = mode * 10 + cur;
-
-  if (check_reconnect (wdata) < 0)
-    return;
-
-   if ((int) generic_thread (do_chmod_thread, wdata))
-    refresh (wdata);
-}
-
-
-static void *
-do_chmod_thread (void * data)
-{
-  GList * filelist, * templist;
-  gftp_window_data * wdata;
-  int success, num, sj;
-  gftp_file * tempfle;
-
-  wdata = data;
-  wdata->request->user_data = (void *) 0x01;
-
-  if (wdata->request->use_threads)
-    {
-      sj = sigsetjmp (jmp_environment, 1);
-      use_jmp_environment = 1;
-    }
-  else
-    sj = 0;
-
-  success = 0;
-  if (sj == 0)
-    { 
-      filelist = wdata->files;
-      templist = GTK_CLIST (wdata->listbox)->selection;
-      num = 0;
-      while (templist != NULL)
-        {
-          templist = get_next_selection (templist, &filelist, &num);
-          tempfle = filelist->data;
-          if (wdata->request->network_timeout > 0)
-            alarm (wdata->request->network_timeout);
-          if (gftp_chmod (wdata->request, tempfle->file, mode) == 0)
-            success = 1;
-          if (!GFTP_IS_CONNECTED (wdata->request))
-            break;
-        }
-      alarm (0);
-    }
-  else
-    {
-      gftp_disconnect (wdata->request);
-      wdata->request->logging_function (gftp_logging_error, 
-                                        wdata->request->user_data,
-                                        _("Operation canceled\n"));
-    }
-
-  if (wdata->request->use_threads)
-    use_jmp_environment = 0;
-
-  wdata->request->user_data = NULL;
-  wdata->request->stopable = 0;
-  return ((void *) success);
-}
-
--- a/src/gtk/delete_dialog.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/delete_dialog.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,13 +20,156 @@
 #include "gftp-gtk.h"
 static const char cvsid[] = "$Id$";
 
-static void askdel 				( gftp_transfer * transfer );
-static void yesCB 				( gftp_transfer * transfer,
-						  gftp_dialog_data * ddata );
-static void * do_delete_thread 			( void *data );
-static void delete_purge_cache 			( gpointer key, 
-						  gpointer value, 
-						  gpointer user_data );
+static void
+delete_purge_cache (gpointer key, gpointer value, gpointer user_data)
+{
+  gftp_request * request;
+  char *olddir;
+
+  request = user_data;
+  olddir = request->directory;
+  request->directory = key;
+  gftp_delete_cache_entry (request, 0);
+  request->directory = olddir;
+  g_free (key);
+}
+
+
+static void *
+do_delete_thread (void *data)
+{
+  gftp_transfer * transfer;
+  char *pos, *tempstr;
+  gftp_file * tempfle;
+  GHashTable * rmhash;
+  GList * templist;
+  int success, sj;
+
+  transfer = data;
+  transfer->fromreq->user_data = (void *) 0x01;
+
+  if (transfer->fromreq->use_threads)
+    {
+      sj = sigsetjmp (jmp_environment, 1);
+      use_jmp_environment = 1;
+    }
+  else
+    sj = 0;
+
+  if (sj == 0)
+    {
+      for (templist = transfer->files; templist->next != NULL; 
+           templist = templist->next);
+
+      rmhash = g_hash_table_new (string_hash_function, string_hash_compare);
+      while (1)
+        {
+          tempfle = templist->data;
+          if (tempfle->isdir)
+            success = gftp_remove_directory (transfer->fromreq, tempfle->file);
+          else
+            success = gftp_remove_file (transfer->fromreq, tempfle->file);
+
+          if (success == 0 && (pos = strrchr (tempfle->file, '/')))
+            {
+              *pos = '\0';
+              if (g_hash_table_lookup (rmhash, tempfle->file) == NULL)
+                {
+                  tempstr = g_strconcat (tempfle->file, NULL);
+                  g_hash_table_insert (rmhash, tempstr, NULL);
+                }
+              *pos = '/';
+            }
+
+          if (templist == transfer->files || 
+              !GFTP_IS_CONNECTED (transfer->fromreq))
+            break;
+          templist = templist->prev;
+        }
+
+      g_hash_table_foreach (rmhash, delete_purge_cache, transfer->fromreq);
+      g_hash_table_destroy (rmhash);
+    }
+  else
+    {
+      gftp_disconnect (transfer->fromreq);
+      transfer->fromreq->logging_function (gftp_logging_error,
+                                        transfer->fromreq->user_data,
+                                        _("Operation canceled\n"));
+    }
+
+  transfer->fromreq->user_data = NULL;
+  transfer->fromreq->stopable = 0;
+
+  if (transfer->fromreq->use_threads)
+    use_jmp_environment = 0;
+
+  return (NULL);
+}
+
+
+static void
+yesCB (gftp_transfer * transfer, gftp_dialog_data * ddata)
+{
+  gftp_window_data * wdata;
+  void * ret;
+
+  g_return_if_fail (transfer != NULL);
+  g_return_if_fail (transfer->files != NULL);
+
+  wdata = transfer->fromwdata;
+  if (check_reconnect (wdata) < 0)
+    return;
+
+  gtk_clist_freeze (GTK_CLIST (wdata->listbox));
+  swap_socks (transfer->fromreq, wdata->request);
+  if (wdata->request->use_threads)
+    {
+      wdata->request->stopable = 1;
+      transfer->fromreq->stopable = 1;
+      gtk_widget_set_sensitive (stop_btn, 1);
+      pthread_create (&wdata->tid, NULL, do_delete_thread, transfer);
+
+      while (transfer->fromreq->stopable)
+        {
+          GDK_THREADS_LEAVE ();
+#if GTK_MAJOR_VERSION == 1
+          g_main_iteration (TRUE);
+#else
+          g_main_context_iteration (NULL, TRUE);
+#endif
+        }
+
+      gtk_widget_set_sensitive (stop_btn, 0);
+      pthread_join (wdata->tid, &ret);
+      wdata->request->stopable = 0;
+    }
+  else
+    ret = do_delete_thread (transfer);
+  swap_socks (wdata->request, transfer->fromreq);
+  free_tdata (transfer);
+
+  if (!GFTP_IS_CONNECTED (wdata->request))
+    disconnect (wdata);
+  else
+    refresh (wdata);
+
+  gtk_clist_thaw (GTK_CLIST (wdata->listbox));
+}
+
+
+static void
+askdel (gftp_transfer * transfer)
+{
+  char *tempstr;
+
+  tempstr = g_strdup_printf (_("Are you sure you want to delete these %ld files and %ld directories"), transfer->numfiles, transfer->numdirs);
+
+  MakeYesNoDialog (_("Delete Files/Directories"), tempstr, 
+                   yesCB, transfer, NULL, NULL);
+  g_free (tempstr);
+}
+
 
 void
 delete_dialog (gpointer data)
@@ -115,153 +258,3 @@
 }
 
 
-static void
-askdel (gftp_transfer * transfer)
-{
-  char *tempstr;
-
-  tempstr = g_strdup_printf (_("Are you sure you want to delete these %ld files and %ld directories"), transfer->numfiles, transfer->numdirs);
-
-  MakeYesNoDialog (_("Delete Files/Directories"), tempstr, 
-                   yesCB, transfer, NULL, NULL);
-  g_free (tempstr);
-}
-
-
-static void
-yesCB (gftp_transfer * transfer, gftp_dialog_data * ddata)
-{
-  gftp_window_data * wdata;
-  void * ret;
-
-  g_return_if_fail (transfer != NULL);
-  g_return_if_fail (transfer->files != NULL);
-
-  wdata = transfer->fromwdata;
-  if (check_reconnect (wdata) < 0)
-    return;
-
-  gtk_clist_freeze (GTK_CLIST (wdata->listbox));
-  swap_socks (transfer->fromreq, wdata->request);
-  if (wdata->request->use_threads)
-    {
-      wdata->request->stopable = 1;
-      transfer->fromreq->stopable = 1;
-      gtk_widget_set_sensitive (stop_btn, 1);
-      pthread_create (&wdata->tid, NULL, do_delete_thread, transfer);
-
-      while (transfer->fromreq->stopable)
-        {
-          GDK_THREADS_LEAVE ();
-#if GTK_MAJOR_VERSION == 1
-          g_main_iteration (TRUE);
-#else
-          g_main_context_iteration (NULL, TRUE);
-#endif
-        }
-
-      gtk_widget_set_sensitive (stop_btn, 0);
-      pthread_join (wdata->tid, &ret);
-      wdata->request->stopable = 0;
-    }
-  else
-    ret = do_delete_thread (transfer);
-  swap_socks (wdata->request, transfer->fromreq);
-  free_tdata (transfer);
-
-  if (!GFTP_IS_CONNECTED (wdata->request))
-    disconnect (wdata);
-  else
-    refresh (wdata);
-
-  gtk_clist_thaw (GTK_CLIST (wdata->listbox));
-}
-
-
-static void *
-do_delete_thread (void *data)
-{
-  gftp_transfer * transfer;
-  char *pos, *tempstr;
-  gftp_file * tempfle;
-  GHashTable * rmhash;
-  GList * templist;
-  int success, sj;
-
-  transfer = data;
-  transfer->fromreq->user_data = (void *) 0x01;
-
-  if (transfer->fromreq->use_threads)
-    {
-      sj = sigsetjmp (jmp_environment, 1);
-      use_jmp_environment = 1;
-    }
-  else
-    sj = 0;
-
-  if (sj == 0)
-    {
-      for (templist = transfer->files; templist->next != NULL; 
-           templist = templist->next);
-
-      rmhash = g_hash_table_new (string_hash_function, string_hash_compare);
-      while (1)
-        {
-          tempfle = templist->data;
-          if (tempfle->isdir)
-            success = gftp_remove_directory (transfer->fromreq, tempfle->file);
-          else
-            success = gftp_remove_file (transfer->fromreq, tempfle->file);
-
-          if (success == 0 && (pos = strrchr (tempfle->file, '/')))
-            {
-              *pos = '\0';
-              if (g_hash_table_lookup (rmhash, tempfle->file) == NULL)
-                {
-                  tempstr = g_strconcat (tempfle->file, NULL);
-                  g_hash_table_insert (rmhash, tempstr, NULL);
-                }
-              *pos = '/';
-            }
-
-          if (templist == transfer->files || 
-              !GFTP_IS_CONNECTED (transfer->fromreq))
-            break;
-          templist = templist->prev;
-        }
-
-      g_hash_table_foreach (rmhash, delete_purge_cache, transfer->fromreq);
-      g_hash_table_destroy (rmhash);
-    }
-  else
-    {
-      gftp_disconnect (transfer->fromreq);
-      transfer->fromreq->logging_function (gftp_logging_error,
-                                        transfer->fromreq->user_data,
-                                        _("Operation canceled\n"));
-    }
-
-  transfer->fromreq->user_data = NULL;
-  transfer->fromreq->stopable = 0;
-
-  if (transfer->fromreq->use_threads)
-    use_jmp_environment = 0;
-
-  return (NULL);
-}
-
-
-static void
-delete_purge_cache (gpointer key, gpointer value, gpointer user_data)
-{
-  gftp_request * request;
-  char *olddir;
-
-  request = user_data;
-  olddir = request->directory;
-  request->directory = key;
-  gftp_delete_cache_entry (request, 0);
-  request->directory = olddir;
-  g_free (key);
-}
-
--- a/src/gtk/dnd.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/dnd.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,9 +20,122 @@
 #include "gftp-gtk.h"
 static const char cvsid[] = "$Id$";
 
-static int dnd_remote_file 			( char *url, 
-						  GList ** transfers, 
-						  gftp_window_data * wdata );
+
+static int
+dnd_remote_file (char *url, GList ** transfers, gftp_window_data * wdata)
+{
+  gftp_request * current_ftpdata;
+  gftp_window_data * fromwdata;
+  gftp_transfer * tdata;
+  gftp_file * newfle;
+  GList * templist;
+  char *str, *pos;
+  int i;
+
+  newfle = g_malloc0 (sizeof (*newfle));
+  newfle->shown = 1;
+  if (url[strlen (url) - 1] == '/') 
+    {
+      newfle->isdir = 1;
+      url[strlen (url) - 1] = '\0';
+    }
+
+  current_ftpdata = gftp_request_new ();
+  current_ftpdata->logging_function = ftp_log;
+
+  if (gftp_parse_url (current_ftpdata, url) != 0) 
+    {
+      ftp_log (gftp_logging_misc, NULL, 
+               _("Drag-N-Drop: Ignoring url %s: Not a valid url\n"), url);
+      gftp_request_destroy (current_ftpdata);
+      free_fdata (newfle);
+      return (0);
+    }
+
+  if ((str = GFTP_GET_DIRECTORY (current_ftpdata)) != NULL) 
+    {
+      if ((pos = strrchr (str, '/')) == NULL) 
+        pos = str;
+      else pos++;
+      *(pos - 1) = '\0';
+      i = 1;
+    }
+  else 
+    {
+      pos = str = GFTP_GET_DIRECTORY (current_ftpdata);
+      i = 0;
+    }
+
+  if (compare_request (current_ftpdata, wdata->request, 1))
+    return (0);
+
+  if (i)
+    {
+      *(pos - 1) = '/';
+      newfle->file = g_malloc (strlen (str) + 1);
+      strcpy (newfle->file, str);
+      *(pos - 1) = '\0';
+    }
+  else
+    {
+      newfle->file = g_malloc (strlen (str) + 1);
+      strcpy (newfle->file, str);
+    }
+  
+  newfle->destfile = g_strconcat (GFTP_GET_DIRECTORY (wdata->request),
+                                     "/", pos, NULL);
+  newfle->ascii = gftp_get_file_transfer_mode (newfle->file, 
+                                wdata->request->data_type) == GFTP_TYPE_ASCII;
+
+  tdata = NULL;
+  templist = *transfers;
+  while (templist != NULL) 
+    {
+      tdata = templist->data;
+      if (compare_request (tdata->fromreq, current_ftpdata, 1))
+        break;
+      templist = templist->next;
+    }
+
+  if (tdata == NULL) 
+    {
+      tdata = g_malloc0 (sizeof (*tdata));
+      tdata->towdata = wdata == &window1 ? &window1 : &window2;
+      fromwdata = wdata == &window1 ? &window2 : &window1;
+      if (fromwdata->request != NULL &&
+          compare_request (fromwdata->request, current_ftpdata, 1))
+        {
+          if (fromwdata->request->password != NULL)
+            gftp_set_password (current_ftpdata, fromwdata->request->password);
+          tdata->fromwdata = fromwdata;
+        }
+      tdata->fromreq = current_ftpdata;
+      tdata->toreq = gftp_request_new ();
+      tdata->toreq->logging_function = ftp_log;
+      tdata->toreq = copy_request (wdata->request);
+      *transfers = g_list_append (*transfers, tdata);
+    }
+  else
+    gftp_request_destroy (current_ftpdata);
+
+  if (newfle->isdir)
+    {
+/* FIXME - need to fix this
+      add_entire_directory (tdata, newfle, 
+		            GFTP_GET_DIRECTORY (tdata->fromhdata->ftpdata), 
+			    GFTP_GET_DIRECTORY (tdata->tohdata->ftpdata), 
+			    tdata->fromhdata->ftpdata);
+*/
+    }
+  else
+    {
+      tdata->files = g_list_append (tdata->files, newfle);
+      if (tdata->curfle == NULL) 
+	tdata->curfle = tdata->files;
+    }
+  return (1);
+}
+
 
 void
 openurl_get_drag_data (GtkWidget * widget, GdkDragContext * context, gint x,
@@ -184,119 +297,3 @@
   gtk_drag_finish (context, finish_drag, FALSE, clk_time);
 }
 
-
-static int
-dnd_remote_file (char *url, GList ** transfers, gftp_window_data * wdata)
-{
-  gftp_request * current_ftpdata;
-  gftp_window_data * fromwdata;
-  gftp_transfer * tdata;
-  gftp_file * newfle;
-  GList * templist;
-  char *str, *pos;
-  int i;
-
-  newfle = g_malloc0 (sizeof (*newfle));
-  newfle->shown = 1;
-  if (url[strlen (url) - 1] == '/') 
-    {
-      newfle->isdir = 1;
-      url[strlen (url) - 1] = '\0';
-    }
-
-  current_ftpdata = gftp_request_new ();
-  current_ftpdata->logging_function = ftp_log;
-
-  if (gftp_parse_url (current_ftpdata, url) != 0) 
-    {
-      ftp_log (gftp_logging_misc, NULL, 
-               _("Drag-N-Drop: Ignoring url %s: Not a valid url\n"), url);
-      gftp_request_destroy (current_ftpdata);
-      free_fdata (newfle);
-      return (0);
-    }
-
-  if ((str = GFTP_GET_DIRECTORY (current_ftpdata)) != NULL) 
-    {
-      if ((pos = strrchr (str, '/')) == NULL) 
-        pos = str;
-      else pos++;
-      *(pos - 1) = '\0';
-      i = 1;
-    }
-  else 
-    {
-      pos = str = GFTP_GET_DIRECTORY (current_ftpdata);
-      i = 0;
-    }
-
-  if (compare_request (current_ftpdata, wdata->request, 1))
-    return (0);
-
-  if (i)
-    {
-      *(pos - 1) = '/';
-      newfle->file = g_malloc (strlen (str) + 1);
-      strcpy (newfle->file, str);
-      *(pos - 1) = '\0';
-    }
-  else
-    {
-      newfle->file = g_malloc (strlen (str) + 1);
-      strcpy (newfle->file, str);
-    }
-  
-  newfle->destfile = g_strconcat (GFTP_GET_DIRECTORY (wdata->request),
-                                     "/", pos, NULL);
-  newfle->ascii = gftp_get_file_transfer_mode (newfle->file, 
-                                wdata->request->data_type) == GFTP_TYPE_ASCII;
-
-  tdata = NULL;
-  templist = *transfers;
-  while (templist != NULL) 
-    {
-      tdata = templist->data;
-      if (compare_request (tdata->fromreq, current_ftpdata, 1))
-        break;
-      templist = templist->next;
-    }
-
-  if (tdata == NULL) 
-    {
-      tdata = g_malloc0 (sizeof (*tdata));
-      tdata->towdata = wdata == &window1 ? &window1 : &window2;
-      fromwdata = wdata == &window1 ? &window2 : &window1;
-      if (fromwdata->request != NULL &&
-          compare_request (fromwdata->request, current_ftpdata, 1))
-        {
-          if (fromwdata->request->password != NULL)
-            gftp_set_password (current_ftpdata, fromwdata->request->password);
-          tdata->fromwdata = fromwdata;
-        }
-      tdata->fromreq = current_ftpdata;
-      tdata->toreq = gftp_request_new ();
-      tdata->toreq->logging_function = ftp_log;
-      tdata->toreq = copy_request (wdata->request);
-      *transfers = g_list_append (*transfers, tdata);
-    }
-  else
-    gftp_request_destroy (current_ftpdata);
-
-  if (newfle->isdir)
-    {
-/* FIXME - need to fix this
-      add_entire_directory (tdata, newfle, 
-		            GFTP_GET_DIRECTORY (tdata->fromhdata->ftpdata), 
-			    GFTP_GET_DIRECTORY (tdata->tohdata->ftpdata), 
-			    tdata->fromhdata->ftpdata);
-*/
-    }
-  else
-    {
-      tdata->files = g_list_append (tdata->files, newfle);
-      if (tdata->curfle == NULL) 
-	tdata->curfle = tdata->files;
-    }
-  return (1);
-}
-
--- a/src/gtk/gftp-gtk.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/gftp-gtk.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,41 +20,6 @@
 #include "gftp-gtk.h"
 static const char cvsid[] = "$Id$";
 
-static gint delete_event 			( GtkWidget * widget, 
-						  GdkEvent * event, 
-						  gpointer data );
-static void destroy 				( GtkWidget * widget, 
-						  gpointer data );
-static RETSIGTYPE sig_child 			( int signo );
-static GtkWidget * CreateFTPWindows 		( GtkWidget * ui );
-static GtkWidget * CreateMenus			( GtkWidget * parent );
-static GtkWidget * CreateToolbar 		( GtkWidget * parent );
-static void doexit 				( GtkWidget * widget, 
-						  gpointer data );
-static int get_column 				( GtkCListColumn * col );
-static void init_gftp 				( int argc, 
-						  char *argv[], 
-						  GtkWidget * parent );
-static void menu_exit 				( GtkWidget * widget, 
-						  gpointer data );
-static GtkWidget * CreateFTPWindow 		( gftp_window_data * wdata,
-						  int width,
-						  int columns[6] );
-static void setup_column 			( GtkWidget * listbox, 
-						  int column, 
-						  int width );
-static gint menu_mouse_click 			( GtkWidget * widget, 
-						  GdkEventButton * event, 
-						  gpointer data );
-static gint list_dblclick 			( GtkWidget * widget, 
-						  GdkEventButton * event, 
-						  gpointer data );
-static void list_doaction 			( gftp_window_data * wdata );
-static gint list_enter 				( GtkWidget * widget, 
-						  GdkEventKey * event, 
-						  gpointer data );
-static void chfunc				( gpointer data );
-
 static GtkItemFactory *log_factory, *dl_factory;
 static GtkWidget * local_frame, * remote_frame, * log_table, * transfer_scroll,
                  * openurl_btn;
@@ -77,86 +42,46 @@
 sigjmp_buf jmp_environment;
 volatile int use_jmp_environment = 0;
 
-
-int
-main (int argc, char **argv)
+static int
+get_column (GtkCListColumn * col)
 {
-  GtkWidget *window, *ui;
-
-#ifdef HAVE_GETTEXT
-  setlocale (LC_ALL, "");
-  bindtextdomain ("gftp", LOCALE_DIR);
-#if GTK_MAJOR_VERSION > 1
-  bind_textdomain_codeset ("gftp", "UTF-8");
-#endif
-  textdomain ("gftp");
-#endif
-
-  g_thread_init (NULL);
-  gtk_set_locale ();
-  gtk_init (&argc, &argv);
+  if (col->auto_resize)
+    return (0);
+  else if (!col->visible)
+    return (-1);
+  else
+    return (col->width);
+}
 
-  signal (SIGCHLD, sig_child);
-  signal (SIGPIPE, SIG_IGN);
-  signal (SIGALRM, signal_handler);
-  signal (SIGINT, signal_handler);
-
-  graphic_hash_table = g_hash_table_new (string_hash_function, string_hash_compare);
-  gftp_read_config_file (argv, 1);
-  if (gftp_parse_command_line (&argc, &argv) != 0)
-    exit (0);
-
-  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
-		      GTK_SIGNAL_FUNC (delete_event), NULL);
-  gtk_signal_connect (GTK_OBJECT (window), "destroy",
-		      GTK_SIGNAL_FUNC (destroy), NULL);
-  gtk_window_set_title (GTK_WINDOW (window), version);
-  gtk_window_set_wmclass (GTK_WINDOW(window), "main", "gFTP");
-  gtk_widget_set_name (window, version);
-  gtk_window_set_policy (GTK_WINDOW (window), TRUE, TRUE, FALSE);
-  gtk_widget_realize (window);
 
-  gftp_icon = open_xpm (window, "gftp.xpm");
-  if (gftp_icon != NULL)
-    {
-      gdk_window_set_icon (window->window, NULL, gftp_icon->pixmap,
-                           gftp_icon->bitmap);
-      gdk_window_set_icon_name (window->window, _("gFTP Icon"));
-    }
-
-  other_wdata = &window1;
-  current_wdata = &window2;
-  ui = CreateFTPWindows (window);
-  gtk_container_add (GTK_CONTAINER (window), ui);
-  gtk_widget_show (window);
+static void
+doexit (GtkWidget * widget, gpointer data)
+{
+  listbox_local_width = GTK_WIDGET (local_frame)->allocation.width;
+  listbox_remote_width = GTK_WIDGET (remote_frame)->allocation.width;
+  listbox_file_height = GTK_WIDGET (remote_frame)->allocation.height;
+  log_height = GTK_WIDGET (log_table)->allocation.height;
+  transfer_height = GTK_WIDGET (transfer_scroll)->allocation.height;
 
-  ftp_log (gftp_logging_misc, NULL,
-	   "%s, Copyright (C) 1998-2002 Brian Masney <", version);
-  ftp_log (gftp_logging_recv, NULL, "masneyb@gftp.org");
-  ftp_log (gftp_logging_misc, NULL,
-	   _(">. If you have any questions, comments, or suggestions about this program, please feel free to email them to me. You can always find out the latest news about gFTP from my website at http://www.gftp.org/\n"));
-  ftp_log (gftp_logging_misc, NULL,
-	   _("gFTP comes with ABSOLUTELY NO WARRANTY; for details, see the COPYING file. This is free software, and you are welcome to redistribute it under certain conditions; for details, see the COPYING file\n"));
+  local_columns[0] = get_column (&GTK_CLIST (window1.listbox)->column[1]);
+  local_columns[1] = get_column (&GTK_CLIST (window1.listbox)->column[2]);
+  local_columns[2] = get_column (&GTK_CLIST (window1.listbox)->column[3]);
+  local_columns[3] = get_column (&GTK_CLIST (window1.listbox)->column[4]);
+  local_columns[4] = get_column (&GTK_CLIST (window1.listbox)->column[5]);
+  local_columns[5] = get_column (&GTK_CLIST (window1.listbox)->column[6]);
 
-  gtk_timeout_add (1000, update_downloads, NULL);
-  gftp_protocols[GFTP_LOCAL_NUM].init (window1.request);
-  if (startup_directory != NULL && *startup_directory != '\0')
-    gftp_set_directory (window1.request, startup_directory);
-  gftp_connect (window1.request);
-  ftp_list_files (&window1, 0);
+  remote_columns[0] = get_column (&GTK_CLIST (window2.listbox)->column[1]);
+  remote_columns[1] = get_column (&GTK_CLIST (window2.listbox)->column[2]);
+  remote_columns[2] = get_column (&GTK_CLIST (window2.listbox)->column[3]);
+  remote_columns[3] = get_column (&GTK_CLIST (window2.listbox)->column[4]);
+  remote_columns[4] = get_column (&GTK_CLIST (window2.listbox)->column[5]);
+  remote_columns[5] = get_column (&GTK_CLIST (window2.listbox)->column[6]);
 
-  /* On the remote window, even though we aren't connected, draw the sort
-     icon on that side */
-  sortrows (GTK_CLIST (window2.listbox), *window2.sortcol, &window2);
+  file_trans_column = get_column (&GTK_CLIST (dlwdw)->column[0]);
 
-  init_gftp (argc, argv, window);
-  gftp_is_started = 1;
-
-  GDK_THREADS_ENTER ();
-  gtk_main ();
-  GDK_THREADS_LEAVE ();
-  return (0);
+  gftp_write_config_file ();
+  gftp_clear_cache_files ();
+  exit (0);
 }
 
 
@@ -188,177 +113,18 @@
 }
 
 
-static GtkWidget *
-CreateFTPWindows (GtkWidget * ui)
+static void
+menu_exit (GtkWidget * widget, gpointer data)
 {
-  GtkWidget *box, *dlbox, *winpane, *dlpane, *logpane, *mainvbox, *tempwid,
-            *button;
-  char *dltitles[2];
-#if GTK_MAJOR_VERSION > 1
-  GtkTextBuffer * textbuf;
-  GtkTextIter iter;
-  GtkTextTag *tag;
-  GdkColor fore;
-#endif
-
-  memset (&window1, 0, sizeof (window1));
-  memset (&window2, 0, sizeof (window2));
-  window1.history = &localhistory;
-  window1.histlen = &localhistlen;
-  window2.history = &remotehistory;
-  window2.histlen = &remotehistlen;
- 
-  mainvbox = gtk_vbox_new (FALSE, 0);
-
-  tempwid = CreateMenus (ui);
-  gtk_box_pack_start (GTK_BOX (mainvbox), tempwid, FALSE, FALSE, 0);
-
-  tempwid = CreateToolbar (ui);
-  gtk_box_pack_start (GTK_BOX (mainvbox), tempwid, FALSE, FALSE, 0);
-
-  winpane = gtk_hpaned_new ();
-
-  box = gtk_hbox_new (FALSE, 0);
-
-  local_frame = CreateFTPWindow (&window1, listbox_local_width, local_columns);
-  window1.sortcol = &local_sortcol;
-  window1.sortasds = &local_sortasds;
-  gtk_box_pack_start (GTK_BOX (box), local_frame, TRUE, TRUE, 0);
-
-  dlbox = gtk_vbox_new (FALSE, 0);
-  gtk_container_border_width (GTK_CONTAINER (dlbox), 5);
-  gtk_box_pack_start (GTK_BOX (box), dlbox, FALSE, FALSE, 0);
-
-#if GTK_MAJOR_VERSION == 1
-  tempwid = toolbar_pixmap (ui, "right.xpm");
-#else
-  tempwid = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
-                                      GTK_ICON_SIZE_SMALL_TOOLBAR);
-#endif
-
-  button = gtk_button_new ();
-  gtk_box_pack_start (GTK_BOX (dlbox), button, TRUE, FALSE, 0);
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     GTK_SIGNAL_FUNC (put_files), NULL);
-  gtk_container_add (GTK_CONTAINER (button), tempwid);
-
-#if GTK_MAJOR_VERSION == 1
-  tempwid = toolbar_pixmap (ui, "left.xpm");
-#else
-  tempwid = gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
-                                      GTK_ICON_SIZE_SMALL_TOOLBAR);
-#endif
-
-  button = gtk_button_new ();
-  gtk_box_pack_start (GTK_BOX (dlbox), button, TRUE, FALSE, 0);
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     GTK_SIGNAL_FUNC (get_files), NULL);
-  gtk_container_add (GTK_CONTAINER (button), tempwid);
-
-  gtk_paned_pack1 (GTK_PANED (winpane), box, 1, 1);
-
-  remote_frame = CreateFTPWindow (&window2, listbox_remote_width, 
-                                  remote_columns);
-  window2.sortcol = &remote_sortcol;
-  window2.sortasds = &remote_sortasds;
-  gtk_paned_pack2 (GTK_PANED (winpane), remote_frame, 1, 1);
-
-  dlpane = gtk_vpaned_new ();
-  gtk_paned_pack1 (GTK_PANED (dlpane), winpane, 1, 1);
-
-  transfer_scroll = gtk_scrolled_window_new (NULL, NULL);
-  gtk_widget_set_size_request (transfer_scroll, -1, transfer_height);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (transfer_scroll),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  if (!delete_event (widget, NULL, data))
+    doexit (widget, data);
+}
 
-  dltitles[0] = _("Filename");
-  dltitles[1] = _("Progress");
-  dlwdw = gtk_ctree_new_with_titles (2, 0, dltitles);
-  gtk_clist_set_selection_mode (GTK_CLIST (dlwdw), GTK_SELECTION_SINGLE);
-  gtk_clist_set_reorderable (GTK_CLIST (dlwdw), 0);
 
-  if (file_trans_column == 0)
-    gtk_clist_set_column_auto_resize (GTK_CLIST (dlwdw), 0, TRUE);
-  else
-    gtk_clist_set_column_width (GTK_CLIST (dlwdw), 0, file_trans_column);
-
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (transfer_scroll),                                          dlwdw);
-  gtk_signal_connect (GTK_OBJECT (dlwdw), "button_press_event",
-		      GTK_SIGNAL_FUNC (menu_mouse_click), (gpointer) dl_factory);
-  gtk_paned_pack2 (GTK_PANED (dlpane), transfer_scroll, 1, 1);
-
-  logpane = gtk_vpaned_new ();
-  gtk_paned_pack1 (GTK_PANED (logpane), dlpane, 1, 1);
-
-  log_table = gtk_table_new (1, 2, FALSE);
-  gtk_widget_set_size_request (log_table, -1, log_height);
-
-#if GTK_MAJOR_VERSION == 1
-  logwdw = gtk_text_new (NULL, NULL);
-
-  gtk_text_set_editable (GTK_TEXT (logwdw), FALSE);
-  gtk_text_set_word_wrap (GTK_TEXT (logwdw), TRUE);
-
-  gtk_table_attach (GTK_TABLE (log_table), logwdw, 0, 1, 0, 1,
-		    GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-		    0, 0);
-  gtk_signal_connect (GTK_OBJECT (logwdw), "button_press_event",
-		      GTK_SIGNAL_FUNC (menu_mouse_click), 
-                      (gpointer) log_factory);
-
-  tempwid = gtk_vscrollbar_new (GTK_TEXT (logwdw)->vadj);
-  gtk_table_attach (GTK_TABLE (log_table), tempwid, 1, 2, 0, 1,
-		    GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
-  logwdw_vadj = GTK_TEXT (logwdw)->vadj;
-#else
-  logwdw = gtk_text_view_new ();
-  gtk_text_view_set_editable (GTK_TEXT_VIEW (logwdw), FALSE);
-  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (logwdw), FALSE);
-  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (logwdw), GTK_WRAP_WORD);
-
-  textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logwdw));
-
-  tag = gtk_text_buffer_create_tag (textbuf, "send", NULL);
-  fore.red = send_color.red;
-  fore.green = send_color.green;
-  fore.blue = send_color.blue;
-  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
-
-  tag = gtk_text_buffer_create_tag (textbuf, "recv", NULL);
-  fore.red = recv_color.red;
-  fore.green = recv_color.green;
-  fore.blue = recv_color.blue;
-  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
-
-  tag = gtk_text_buffer_create_tag (textbuf, "error", NULL);
-  fore.red = error_color.red;
-  fore.green = error_color.green;
-  fore.blue = error_color.blue;
-  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
-
-  tag = gtk_text_buffer_create_tag (textbuf, "misc", NULL);
-  fore.red = misc_color.red;
-  fore.green = misc_color.green;
-  fore.blue = misc_color.blue;
-  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
-
-  tempwid = gtk_scrolled_window_new (NULL, NULL);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tempwid),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
-  gtk_container_add (GTK_CONTAINER (tempwid), logwdw);
-  gtk_table_attach (GTK_TABLE (log_table), tempwid, 0, 1, 0, 1,
-		    GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
-		    0, 0);
-  logwdw_vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (tempwid));
-  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0);
-  logwdw_textmark = gtk_text_buffer_create_mark (textbuf, "end", &iter, 1);
-#endif
-  gtk_paned_pack2 (GTK_PANED (logpane), log_table, 1, 1);
-  gtk_box_pack_start (GTK_BOX (mainvbox), logpane, TRUE, TRUE, 0);
-
-  gtk_widget_show_all (mainvbox);
-  return (mainvbox);
+static void
+chfunc (gpointer data)
+{
+  chdir_dialog (data);
 }
 
 
@@ -665,66 +431,113 @@
 
 
 static void
-doexit (GtkWidget * widget, gpointer data)
+setup_column (GtkWidget * listbox, int column, int width)
 {
-  listbox_local_width = GTK_WIDGET (local_frame)->allocation.width;
-  listbox_remote_width = GTK_WIDGET (remote_frame)->allocation.width;
-  listbox_file_height = GTK_WIDGET (remote_frame)->allocation.height;
-  log_height = GTK_WIDGET (log_table)->allocation.height;
-  transfer_height = GTK_WIDGET (transfer_scroll)->allocation.height;
-
-  local_columns[0] = get_column (&GTK_CLIST (window1.listbox)->column[1]);
-  local_columns[1] = get_column (&GTK_CLIST (window1.listbox)->column[2]);
-  local_columns[2] = get_column (&GTK_CLIST (window1.listbox)->column[3]);
-  local_columns[3] = get_column (&GTK_CLIST (window1.listbox)->column[4]);
-  local_columns[4] = get_column (&GTK_CLIST (window1.listbox)->column[5]);
-  local_columns[5] = get_column (&GTK_CLIST (window1.listbox)->column[6]);
-
-  remote_columns[0] = get_column (&GTK_CLIST (window2.listbox)->column[1]);
-  remote_columns[1] = get_column (&GTK_CLIST (window2.listbox)->column[2]);
-  remote_columns[2] = get_column (&GTK_CLIST (window2.listbox)->column[3]);
-  remote_columns[3] = get_column (&GTK_CLIST (window2.listbox)->column[4]);
-  remote_columns[4] = get_column (&GTK_CLIST (window2.listbox)->column[5]);
-  remote_columns[5] = get_column (&GTK_CLIST (window2.listbox)->column[6]);
-
-  file_trans_column = get_column (&GTK_CLIST (dlwdw)->column[0]);
-
-  gftp_write_config_file ();
-  gftp_clear_cache_files ();
-  exit (0);
+  if (width == 0)
+    gtk_clist_set_column_auto_resize (GTK_CLIST (listbox), column, TRUE);
+  else if (width == -1)
+    gtk_clist_set_column_visibility (GTK_CLIST (listbox), column, FALSE);
+  else
+    gtk_clist_set_column_width (GTK_CLIST (listbox), column, width);
 }
 
 
-static int
-get_column (GtkCListColumn * col)
+static void
+list_doaction (gftp_window_data * wdata)
 {
-  if (col->auto_resize)
-    return (0);
-  else if (!col->visible)
-    return (-1);
-  else
-    return (col->width);
-}
+  GList *templist, *filelist;
+  int num, dir, success;
+  gftp_file *tempfle;
+
+  filelist = wdata->files;
+  templist = GTK_CLIST (wdata->listbox)->selection;
+  num = 0;
+  templist = get_next_selection (templist, &filelist, &num);
+  tempfle = (gftp_file *) filelist->data;
+
+  dir = tempfle->isdir;
+  success = 0;
 
+  if (tempfle->islink || tempfle->isdir)
+    success = chdir_dialog (wdata);
 
-void
-init_gftp (int argc, char *argv[], GtkWidget * parent)
-{
-  if (argc == 2 && strncmp (argv[1], "--", 2) != 0)
+  if (!dir && !success)
     {
-      if (gftp_parse_url (window2.request, argv[1]) == 0)
-	ftp_connect (&window2, window2.request, 1);
-      else
-	gftp_usage ();
+      switch (listbox_dblclick_action)
+        {
+          case 0:
+            view_dialog (wdata);
+            break;
+          case 1:
+            edit_dialog (wdata);
+            break;
+          case 2:
+            if (wdata == &window2)
+              get_files (wdata);
+            else
+              put_files (wdata);
+            break;
+        }
     }
 }
 
 
-static void
-menu_exit (GtkWidget * widget, gpointer data)
+static gint
+list_enter (GtkWidget * widget, GdkEventKey * event, gpointer data)
+{
+  gftp_window_data * wdata;
+
+  wdata = data;
+  if (!GFTP_IS_CONNECTED (wdata->request))
+    return (TRUE);
+
+  if (event->type == GDK_KEY_PRESS && 
+           (event->keyval == GDK_KP_Delete || event->keyval == GDK_Delete))
+    {
+      delete_dialog (wdata);
+      return (FALSE);
+    }
+  else if (IS_ONE_SELECTED (wdata) && event->type == GDK_KEY_PRESS && 
+      event->keyval == GDK_Return)
+    {
+      list_doaction (wdata);
+      return (FALSE);
+    }
+  return (TRUE);
+}
+
+
+static gint
+list_dblclick (GtkWidget * widget, GdkEventButton * event, gpointer data)
 {
-  if (!delete_event (widget, NULL, data))
-    doexit (widget, data);
+  gftp_window_data * wdata;
+
+  wdata = data;
+  if (event->button == 3)
+    gtk_item_factory_popup (wdata->ifactory, (guint) event->x_root,
+                            (guint) event->y_root, 3, event->time);
+  else if (!GFTP_IS_CONNECTED (wdata->request) || !IS_ONE_SELECTED (wdata))
+    return (TRUE);
+
+#if GTK_MAJOR_VERSION == 1
+  if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
+    {
+      list_doaction (wdata);
+      return (FALSE);
+    }
+  return (TRUE);
+#else
+  /* If we're using GTK 2.0, if I connect to the button_press_event signal,
+     whenever I get the GDK_2BUTTON_PRESS event, nothing is selected inside
+     the clist. But if I connect_after to the button_release_event, it seems
+     to only get called when we double click */
+  if (event->button == 1)
+    {
+      list_doaction (wdata);
+      return (FALSE);
+    }
+  return (TRUE);
+#endif
 }
 
 
@@ -821,18 +634,6 @@
 }
 
 
-static void
-setup_column (GtkWidget * listbox, int column, int width)
-{
-  if (width == 0)
-    gtk_clist_set_column_auto_resize (GTK_CLIST (listbox), column, TRUE);
-  else if (width == -1)
-    gtk_clist_set_column_visibility (GTK_CLIST (listbox), column, FALSE);
-  else
-    gtk_clist_set_column_width (GTK_CLIST (listbox), column, width);
-}
-
-
 static gint
 menu_mouse_click (GtkWidget * widget, GdkEventButton * event, gpointer data)
 {
@@ -846,112 +647,193 @@
 }
 
 
-static gint
-list_dblclick (GtkWidget * widget, GdkEventButton * event, gpointer data)
+static GtkWidget *
+CreateFTPWindows (GtkWidget * ui)
 {
-  gftp_window_data * wdata;
+  GtkWidget *box, *dlbox, *winpane, *dlpane, *logpane, *mainvbox, *tempwid,
+            *button;
+  char *dltitles[2];
+#if GTK_MAJOR_VERSION > 1
+  GtkTextBuffer * textbuf;
+  GtkTextIter iter;
+  GtkTextTag *tag;
+  GdkColor fore;
+#endif
+
+  memset (&window1, 0, sizeof (window1));
+  memset (&window2, 0, sizeof (window2));
+  window1.history = &localhistory;
+  window1.histlen = &localhistlen;
+  window2.history = &remotehistory;
+  window2.histlen = &remotehistlen;
+ 
+  mainvbox = gtk_vbox_new (FALSE, 0);
+
+  tempwid = CreateMenus (ui);
+  gtk_box_pack_start (GTK_BOX (mainvbox), tempwid, FALSE, FALSE, 0);
 
-  wdata = data;
-  if (event->button == 3)
-    gtk_item_factory_popup (wdata->ifactory, (guint) event->x_root,
-                            (guint) event->y_root, 3, event->time);
-  else if (!GFTP_IS_CONNECTED (wdata->request) || !IS_ONE_SELECTED (wdata))
-    return (TRUE);
+  tempwid = CreateToolbar (ui);
+  gtk_box_pack_start (GTK_BOX (mainvbox), tempwid, FALSE, FALSE, 0);
+
+  winpane = gtk_hpaned_new ();
+
+  box = gtk_hbox_new (FALSE, 0);
+
+  local_frame = CreateFTPWindow (&window1, listbox_local_width, local_columns);
+  window1.sortcol = &local_sortcol;
+  window1.sortasds = &local_sortasds;
+  gtk_box_pack_start (GTK_BOX (box), local_frame, TRUE, TRUE, 0);
+
+  dlbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_border_width (GTK_CONTAINER (dlbox), 5);
+  gtk_box_pack_start (GTK_BOX (box), dlbox, FALSE, FALSE, 0);
+
+#if GTK_MAJOR_VERSION == 1
+  tempwid = toolbar_pixmap (ui, "right.xpm");
+#else
+  tempwid = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
+                                      GTK_ICON_SIZE_SMALL_TOOLBAR);
+#endif
+
+  button = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (dlbox), button, TRUE, FALSE, 0);
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     GTK_SIGNAL_FUNC (put_files), NULL);
+  gtk_container_add (GTK_CONTAINER (button), tempwid);
 
 #if GTK_MAJOR_VERSION == 1
-  if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
-    {
-      list_doaction (wdata);
-      return (FALSE);
-    }
-  return (TRUE);
+  tempwid = toolbar_pixmap (ui, "left.xpm");
 #else
-  /* If we're using GTK 2.0, if I connect to the button_press_event signal,
-     whenever I get the GDK_2BUTTON_PRESS event, nothing is selected inside
-     the clist. But if I connect_after to the button_release_event, it seems
-     to only get called when we double click */
-  if (event->button == 1)
-    {
-      list_doaction (wdata);
-      return (FALSE);
-    }
-  return (TRUE);
+  tempwid = gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
+                                      GTK_ICON_SIZE_SMALL_TOOLBAR);
 #endif
+
+  button = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (dlbox), button, TRUE, FALSE, 0);
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     GTK_SIGNAL_FUNC (get_files), NULL);
+  gtk_container_add (GTK_CONTAINER (button), tempwid);
+
+  gtk_paned_pack1 (GTK_PANED (winpane), box, 1, 1);
+
+  remote_frame = CreateFTPWindow (&window2, listbox_remote_width, 
+                                  remote_columns);
+  window2.sortcol = &remote_sortcol;
+  window2.sortasds = &remote_sortasds;
+  gtk_paned_pack2 (GTK_PANED (winpane), remote_frame, 1, 1);
+
+  dlpane = gtk_vpaned_new ();
+  gtk_paned_pack1 (GTK_PANED (dlpane), winpane, 1, 1);
+
+  transfer_scroll = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_size_request (transfer_scroll, -1, transfer_height);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (transfer_scroll),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+  dltitles[0] = _("Filename");
+  dltitles[1] = _("Progress");
+  dlwdw = gtk_ctree_new_with_titles (2, 0, dltitles);
+  gtk_clist_set_selection_mode (GTK_CLIST (dlwdw), GTK_SELECTION_SINGLE);
+  gtk_clist_set_reorderable (GTK_CLIST (dlwdw), 0);
+
+  if (file_trans_column == 0)
+    gtk_clist_set_column_auto_resize (GTK_CLIST (dlwdw), 0, TRUE);
+  else
+    gtk_clist_set_column_width (GTK_CLIST (dlwdw), 0, file_trans_column);
+
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (transfer_scroll),                                          dlwdw);
+  gtk_signal_connect (GTK_OBJECT (dlwdw), "button_press_event",
+		      GTK_SIGNAL_FUNC (menu_mouse_click), (gpointer) dl_factory);
+  gtk_paned_pack2 (GTK_PANED (dlpane), transfer_scroll, 1, 1);
+
+  logpane = gtk_vpaned_new ();
+  gtk_paned_pack1 (GTK_PANED (logpane), dlpane, 1, 1);
+
+  log_table = gtk_table_new (1, 2, FALSE);
+  gtk_widget_set_size_request (log_table, -1, log_height);
+
+#if GTK_MAJOR_VERSION == 1
+  logwdw = gtk_text_new (NULL, NULL);
+
+  gtk_text_set_editable (GTK_TEXT (logwdw), FALSE);
+  gtk_text_set_word_wrap (GTK_TEXT (logwdw), TRUE);
+
+  gtk_table_attach (GTK_TABLE (log_table), logwdw, 0, 1, 0, 1,
+		    GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+		    0, 0);
+  gtk_signal_connect (GTK_OBJECT (logwdw), "button_press_event",
+		      GTK_SIGNAL_FUNC (menu_mouse_click), 
+                      (gpointer) log_factory);
+
+  tempwid = gtk_vscrollbar_new (GTK_TEXT (logwdw)->vadj);
+  gtk_table_attach (GTK_TABLE (log_table), tempwid, 1, 2, 0, 1,
+		    GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
+  logwdw_vadj = GTK_TEXT (logwdw)->vadj;
+#else
+  logwdw = gtk_text_view_new ();
+  gtk_text_view_set_editable (GTK_TEXT_VIEW (logwdw), FALSE);
+  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (logwdw), FALSE);
+  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (logwdw), GTK_WRAP_WORD);
+
+  textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logwdw));
+
+  tag = gtk_text_buffer_create_tag (textbuf, "send", NULL);
+  fore.red = send_color.red;
+  fore.green = send_color.green;
+  fore.blue = send_color.blue;
+  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
+
+  tag = gtk_text_buffer_create_tag (textbuf, "recv", NULL);
+  fore.red = recv_color.red;
+  fore.green = recv_color.green;
+  fore.blue = recv_color.blue;
+  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
+
+  tag = gtk_text_buffer_create_tag (textbuf, "error", NULL);
+  fore.red = error_color.red;
+  fore.green = error_color.green;
+  fore.blue = error_color.blue;
+  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
+
+  tag = gtk_text_buffer_create_tag (textbuf, "misc", NULL);
+  fore.red = misc_color.red;
+  fore.green = misc_color.green;
+  fore.blue = misc_color.blue;
+  g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
+
+  tempwid = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tempwid),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  gtk_container_add (GTK_CONTAINER (tempwid), logwdw);
+  gtk_table_attach (GTK_TABLE (log_table), tempwid, 0, 1, 0, 1,
+		    GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+		    0, 0);
+  logwdw_vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (tempwid));
+  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0);
+  logwdw_textmark = gtk_text_buffer_create_mark (textbuf, "end", &iter, 1);
+#endif
+  gtk_paned_pack2 (GTK_PANED (logpane), log_table, 1, 1);
+  gtk_box_pack_start (GTK_BOX (mainvbox), logpane, TRUE, TRUE, 0);
+
+  gtk_widget_show_all (mainvbox);
+  return (mainvbox);
 }
 
 
-static void
-list_doaction (gftp_window_data * wdata)
+void
+init_gftp (int argc, char *argv[], GtkWidget * parent)
 {
-  GList *templist, *filelist;
-  int num, dir, success;
-  gftp_file *tempfle;
-
-  filelist = wdata->files;
-  templist = GTK_CLIST (wdata->listbox)->selection;
-  num = 0;
-  templist = get_next_selection (templist, &filelist, &num);
-  tempfle = (gftp_file *) filelist->data;
-
-  dir = tempfle->isdir;
-  success = 0;
-
-  if (tempfle->islink || tempfle->isdir)
-    success = chdir_dialog (wdata);
-
-  if (!dir && !success)
+  if (argc == 2 && strncmp (argv[1], "--", 2) != 0)
     {
-      switch (listbox_dblclick_action)
-        {
-          case 0:
-            view_dialog (wdata);
-            break;
-          case 1:
-            edit_dialog (wdata);
-            break;
-          case 2:
-            if (wdata == &window2)
-              get_files (wdata);
-            else
-              put_files (wdata);
-            break;
-        }
+      if (gftp_parse_url (window2.request, argv[1]) == 0)
+	ftp_connect (&window2, window2.request, 1);
+      else
+	gftp_usage ();
     }
 }
 
 
-static gint
-list_enter (GtkWidget * widget, GdkEventKey * event, gpointer data)
-{
-  gftp_window_data * wdata;
-
-  wdata = data;
-  if (!GFTP_IS_CONNECTED (wdata->request))
-    return (TRUE);
-
-  if (event->type == GDK_KEY_PRESS && 
-           (event->keyval == GDK_KP_Delete || event->keyval == GDK_Delete))
-    {
-      delete_dialog (wdata);
-      return (FALSE);
-    }
-  else if (IS_ONE_SELECTED (wdata) && event->type == GDK_KEY_PRESS && 
-      event->keyval == GDK_Return)
-    {
-      list_doaction (wdata);
-      return (FALSE);
-    }
-  return (TRUE);
-}
-
-
-static void
-chfunc (gpointer data)
-{
-  chdir_dialog (data);
-}
-
-
 void
 toolbar_hostedit (GtkWidget * widget, gpointer data)
 {
@@ -1095,3 +977,86 @@
     pthread_kill (window2.tid, SIGINT);
 }
 
+
+int
+main (int argc, char **argv)
+{
+  GtkWidget *window, *ui;
+
+#ifdef HAVE_GETTEXT
+  setlocale (LC_ALL, "");
+  bindtextdomain ("gftp", LOCALE_DIR);
+#if GTK_MAJOR_VERSION > 1
+  bind_textdomain_codeset ("gftp", "UTF-8");
+#endif
+  textdomain ("gftp");
+#endif
+
+  g_thread_init (NULL);
+  gtk_set_locale ();
+  gtk_init (&argc, &argv);
+
+  signal (SIGCHLD, sig_child);
+  signal (SIGPIPE, SIG_IGN);
+  signal (SIGALRM, signal_handler);
+  signal (SIGINT, signal_handler);
+
+  graphic_hash_table = g_hash_table_new (string_hash_function, string_hash_compare);
+  gftp_read_config_file (argv, 1);
+  if (gftp_parse_command_line (&argc, &argv) != 0)
+    exit (0);
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+		      GTK_SIGNAL_FUNC (delete_event), NULL);
+  gtk_signal_connect (GTK_OBJECT (window), "destroy",
+		      GTK_SIGNAL_FUNC (destroy), NULL);
+  gtk_window_set_title (GTK_WINDOW (window), version);
+  gtk_window_set_wmclass (GTK_WINDOW(window), "main", "gFTP");
+  gtk_widget_set_name (window, version);
+  gtk_window_set_policy (GTK_WINDOW (window), TRUE, TRUE, FALSE);
+  gtk_widget_realize (window);
+
+  gftp_icon = open_xpm (window, "gftp.xpm");
+  if (gftp_icon != NULL)
+    {
+      gdk_window_set_icon (window->window, NULL, gftp_icon->pixmap,
+                           gftp_icon->bitmap);
+      gdk_window_set_icon_name (window->window, _("gFTP Icon"));
+    }
+
+  other_wdata = &window1;
+  current_wdata = &window2;
+  ui = CreateFTPWindows (window);
+  gtk_container_add (GTK_CONTAINER (window), ui);
+  gtk_widget_show (window);
+
+  ftp_log (gftp_logging_misc, NULL,
+	   "%s, Copyright (C) 1998-2002 Brian Masney <", version);
+  ftp_log (gftp_logging_recv, NULL, "masneyb@gftp.org");
+  ftp_log (gftp_logging_misc, NULL,
+	   _(">. If you have any questions, comments, or suggestions about this program, please feel free to email them to me. You can always find out the latest news about gFTP from my website at http://www.gftp.org/\n"));
+  ftp_log (gftp_logging_misc, NULL,
+	   _("gFTP comes with ABSOLUTELY NO WARRANTY; for details, see the COPYING file. This is free software, and you are welcome to redistribute it under certain conditions; for details, see the COPYING file\n"));
+
+  gtk_timeout_add (1000, update_downloads, NULL);
+  gftp_protocols[GFTP_LOCAL_NUM].init (window1.request);
+  if (startup_directory != NULL && *startup_directory != '\0')
+    gftp_set_directory (window1.request, startup_directory);
+  gftp_connect (window1.request);
+  ftp_list_files (&window1, 0);
+
+  /* On the remote window, even though we aren't connected, draw the sort
+     icon on that side */
+  sortrows (GTK_CLIST (window2.listbox), *window2.sortcol, &window2);
+
+  init_gftp (argc, argv, window);
+  gftp_is_started = 1;
+
+  GDK_THREADS_ENTER ();
+  gtk_main ();
+  GDK_THREADS_LEAVE ();
+  return (0);
+}
+
+
--- a/src/gtk/menu-items.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/menu-items.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,10 +20,6 @@
 #include <gftp-gtk.h>
 static const char cvsid[] = "$Id$";
 
-static int do_change_dir			( gftp_window_data * wdata,
-						  char * directory );
-static void *do_change_dir_thread 		( void * data );
-
 void
 change_setting (gftp_window_data * wdata, int menuitem, GtkWidget * checkmenu)
 {
@@ -422,6 +418,85 @@
 }
 
 
+static void *
+do_change_dir_thread (void * data)
+{
+  gftp_window_data * wdata;
+  int success, sj;
+
+  wdata = data;
+  wdata->request->user_data = (void *) 0x01;
+
+  if (wdata->request->use_threads)
+    {
+      sj = sigsetjmp (jmp_environment, 1);
+      use_jmp_environment = 1;
+    }
+  else
+    sj = 0;
+
+  success = 0;
+  if (sj == 0) 
+    {
+      if (wdata->request->network_timeout > 0)
+        alarm (wdata->request->network_timeout);
+      success = gftp_set_directory (wdata->request, wdata->request->directory);
+      alarm (0);
+    }
+  else
+    {
+      gftp_disconnect (wdata->request);
+      wdata->request->logging_function (gftp_logging_error,
+                                        wdata->request->user_data,
+                                        _("Operation canceled\n"));
+    }
+
+  if (wdata->request->use_threads)
+    use_jmp_environment = 0;
+
+  wdata->request->user_data = NULL;
+  wdata->request->stopable = 0;
+  return ((void *) success);
+}
+
+
+static int
+do_change_dir (gftp_window_data * wdata, char *directory)
+{
+  char *olddir;
+  int ret;
+
+  if (directory != wdata->request->directory)
+    {
+      olddir = wdata->request->directory;
+      wdata->request->directory = g_malloc (strlen (directory) + 1);
+      strcpy (wdata->request->directory, directory);
+    }
+  else
+    olddir = NULL;
+
+  ret = (int) generic_thread (do_change_dir_thread, wdata);
+
+  if (!GFTP_IS_CONNECTED (wdata->request))
+    {
+      disconnect (wdata);
+      if (olddir != NULL)
+        g_free (olddir);
+      return (-2);
+    }
+
+  if (ret != 0)
+    {
+      g_free (wdata->request->directory);
+      wdata->request->directory = olddir;
+    }
+  else
+    g_free (olddir);
+
+  return (ret);
+}
+
+
 int
 chdir_edit (GtkWidget * widget, gpointer data)
 {
@@ -505,85 +580,6 @@
 }
 
 
-static int
-do_change_dir (gftp_window_data * wdata, char *directory)
-{
-  char *olddir;
-  int ret;
-
-  if (directory != wdata->request->directory)
-    {
-      olddir = wdata->request->directory;
-      wdata->request->directory = g_malloc (strlen (directory) + 1);
-      strcpy (wdata->request->directory, directory);
-    }
-  else
-    olddir = NULL;
-
-  ret = (int) generic_thread (do_change_dir_thread, wdata);
-
-  if (!GFTP_IS_CONNECTED (wdata->request))
-    {
-      disconnect (wdata);
-      if (olddir != NULL)
-        g_free (olddir);
-      return (-2);
-    }
-
-  if (ret != 0)
-    {
-      g_free (wdata->request->directory);
-      wdata->request->directory = olddir;
-    }
-  else
-    g_free (olddir);
-
-  return (ret);
-}
-
-
-static void *
-do_change_dir_thread (void * data)
-{
-  gftp_window_data * wdata;
-  int success, sj;
-
-  wdata = data;
-  wdata->request->user_data = (void *) 0x01;
-
-  if (wdata->request->use_threads)
-    {
-      sj = sigsetjmp (jmp_environment, 1);
-      use_jmp_environment = 1;
-    }
-  else
-    sj = 0;
-
-  success = 0;
-  if (sj == 0) 
-    {
-      if (wdata->request->network_timeout > 0)
-        alarm (wdata->request->network_timeout);
-      success = gftp_set_directory (wdata->request, wdata->request->directory);
-      alarm (0);
-    }
-  else
-    {
-      gftp_disconnect (wdata->request);
-      wdata->request->logging_function (gftp_logging_error,
-                                        wdata->request->user_data,
-                                        _("Operation canceled\n"));
-    }
-
-  if (wdata->request->use_threads)
-    use_jmp_environment = 0;
-
-  wdata->request->user_data = NULL;
-  wdata->request->stopable = 0;
-  return ((void *) success);
-}
-
-
 void 
 clearlog (gpointer data)
 {
--- a/src/gtk/misc-gtk.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/misc-gtk.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,15 +20,6 @@
 #include <gftp-gtk.h>
 static const char cvsid[] = "$Id$";
 
-static void set_menu_sensitive 			( gftp_window_data * wdata,
-						  char *path, 
-						  int sensitive );
-static gint delete_event 			( GtkWidget * widget, 
-						  GdkEvent * event, 
-						  gpointer data );
-static void trans_stop_button 			( GtkWidget * widget,
-						  gpointer data );
-
 static GtkWidget * statuswid;
 
 
@@ -298,6 +289,29 @@
 }
 
 
+static void
+set_menu_sensitive (gftp_window_data * wdata, char *path, int sensitive)
+{
+  GtkWidget * tempwid;
+  char * pos;
+
+  tempwid = NULL;
+
+  if (factory != NULL)
+    tempwid = gtk_item_factory_get_widget (factory, path);
+  if (tempwid)
+    gtk_widget_set_sensitive (tempwid, sensitive);
+
+  if ((pos = strchr (path + 1, '/')) == NULL)
+    pos = path;
+
+  if (wdata->ifactory)
+    tempwid = gtk_item_factory_get_widget (wdata->ifactory, pos);
+  if (tempwid)
+    gtk_widget_set_sensitive (tempwid, sensitive);
+}
+
+
 void
 update_window (gftp_window_data * wdata)
 {
@@ -369,29 +383,6 @@
 }  
 
 
-static void
-set_menu_sensitive (gftp_window_data * wdata, char *path, int sensitive)
-{
-  GtkWidget * tempwid;
-  char * pos;
-
-  tempwid = NULL;
-
-  if (factory != NULL)
-    tempwid = gtk_item_factory_get_widget (factory, path);
-  if (tempwid)
-    gtk_widget_set_sensitive (tempwid, sensitive);
-
-  if ((pos = strchr (path + 1, '/')) == NULL)
-    pos = path;
-
-  if (wdata->ifactory)
-    tempwid = gtk_item_factory_get_widget (wdata->ifactory, pos);
-  if (tempwid)
-    gtk_widget_set_sensitive (tempwid, sensitive);
-}
-
-
 GtkWidget *
 toolbar_pixmap (GtkWidget * widget, char *filename)
 {
@@ -805,8 +796,8 @@
     gtk_clist_set_text (GTK_CLIST (wdata->listbox), clist_num, 1, fle->file);
 
   if (fle->attribs && (*fle->attribs == 'b' || *fle->attribs == 'c'))
-    tempstr = g_strdup_printf ("%d, %d", (int) fle->size >> 16,
-                               (int) fle->size & 0xFF);
+    tempstr = g_strdup_printf ("%d, %d", major (fle->size),
+                               minor (fle->size));
   else
     tempstr = insert_commas (fle->size, NULL, 0);
 
@@ -1107,6 +1098,23 @@
 }
 
 
+static gint
+delete_event (GtkWidget * widget, GdkEvent * event, gpointer data)
+{
+  return (TRUE);
+}
+
+
+static void
+trans_stop_button (GtkWidget * widget, gpointer data)
+{
+  gftp_transfer * transfer;
+
+  transfer = data;
+  pthread_kill (((gftp_window_data *) transfer->fromwdata)->tid, SIGINT);
+}
+
+
 void
 update_directory_download_progress (gftp_transfer * transfer)
 {
@@ -1220,22 +1228,6 @@
 }
 
 
-static gint
-delete_event (GtkWidget * widget, GdkEvent * event, gpointer data)
-{
-  return (TRUE);
-}
-
-
-static void
-trans_stop_button (GtkWidget * widget, gpointer data)
-{
-  gftp_transfer * transfer;
-
-  transfer = data;
-  pthread_kill (((gftp_window_data *) transfer->fromwdata)->tid, SIGINT);
-}
-
 void
 display_cached_logs (void)
 {
--- a/src/gtk/options_dialog.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/options_dialog.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,25 +20,6 @@
 #include <gftp-gtk.h>
 static const char cvsid[] = "$Id$";
 
-static void make_proxy_hosts_tab 		( GtkWidget * notebook );
-static void add_host_to_listbox 		( GList * templist );
-static void add_proxy_host 			( GtkWidget * widget, 
-						  gpointer data );
-static void add_toggle 				( GtkWidget * widget, 
-						  gpointer data );
-static void add_ok 				( GtkWidget * widget, 
-						  gpointer data );
-static void delete_proxy_host 			( GtkWidget * widget, 
-						  gpointer data );
-static void proxy_toggle 			( GtkList * list, 
-						  GtkWidget * child, 
-						  gpointer data );
-static void apply_changes 			( GtkWidget * widget, 
-						  gpointer data );
-static void clean_old_changes 			( GtkWidget * widget, 
-						  gpointer data );
-static char *get_proxy_config 			( void );
-
 static GtkWidget * proxy_text, * proxy_list, * new_proxy_domain, * network1,
                  * network2, * network3, * network4, * netmask1, * netmask2, 
                  * netmask3, * netmask4, * domain_active, * proxy_combo,
@@ -46,6 +27,178 @@
 static GList * new_proxy_hosts;
 static char *custom_proxy;
 
+
+static void
+clean_old_changes (GtkWidget * widget, gpointer data)
+{
+  gftp_proxy_hosts *hosts;
+  GList *templist;
+
+  templist = new_proxy_hosts;
+  while (templist != NULL)
+    {
+      hosts = templist->data;
+      if (hosts->domain)
+        g_free (hosts->domain);
+      g_free (hosts);
+      templist = templist->next;
+    }
+  g_list_free (new_proxy_hosts);
+  new_proxy_hosts = NULL;
+
+  if (custom_proxy != NULL)
+    {
+      g_free (custom_proxy);
+      custom_proxy = NULL;
+    }
+}
+
+
+static char *
+get_proxy_config (void)
+{
+  char *newstr, *oldstr, *pos, *endpos, *textstr;
+  guint len;
+#if GTK_MAJOR_VERSION == 1
+  char tmp[128];
+#else
+  GtkTextBuffer * textbuf;
+  GtkTextIter iter, iter2;
+#endif
+
+  textstr = NULL;
+  newstr = g_malloc (1);
+  *newstr = '\0';
+
+#if GTK_MAJOR_VERSION == 1
+  /*
+     GTK_TEXT uses wchar_t instead of char in environment of multibyte encoding
+     locale (ex Japanese),  so we must convert from wide character 
+     to multibyte charator....   Yasuyuki Furukawa (yasu@on.cs.keio.ac.jp)
+   */
+  if (GTK_TEXT (proxy_text)->use_wchar)
+    {
+      wcstombs (tmp, (wchar_t *) GTK_TEXT (proxy_text)->text.wc,
+                sizeof (tmp));
+      pos = tmp;
+    }
+  else
+    {
+      oldstr = (char *) GTK_TEXT (proxy_text)->text.ch; 
+      len = gtk_text_get_length (GTK_TEXT (proxy_text));
+      textstr = g_malloc (len + 1);
+      strncpy (textstr, oldstr, len);
+      textstr[len] = '\0';
+      pos = textstr;
+    }
+#else
+  textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (proxy_text));
+  len = gtk_text_buffer_get_char_count (textbuf);
+  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0);
+  gtk_text_buffer_get_iter_at_offset (textbuf, &iter2, len - 1);
+  pos = textstr = gtk_text_buffer_get_text (textbuf, &iter, &iter2, 0);
+#endif
+
+  do
+    {
+      if ((endpos = strchr (pos, '\n')) != NULL)
+        *endpos = '\0';
+      oldstr = newstr;
+      if (endpos != NULL)
+        newstr = g_strconcat (newstr, pos, "%n", NULL);
+      else
+        newstr = g_strconcat (newstr, pos, NULL);
+      g_free (oldstr);
+      if (endpos != NULL)
+        {
+          *endpos = '\n';
+          pos = endpos + 1;
+        }
+    }
+  while (endpos != NULL);
+
+#if GTK_MAJOR_VERSION == 1
+  if (!GTK_TEXT (proxy_text)->use_wchar)
+    g_free (textstr);
+#else
+  g_free (textstr);
+#endif
+
+  return (newstr);
+}
+
+
+static void
+apply_changes (GtkWidget * widget, gpointer data)
+{
+  const char *tempstr;
+  int num, found, i;
+  GList *templist;
+
+  for (num = 0; config_file_vars[num].var != NULL; num++)
+    {
+      if (config_file_vars[num].widget != NULL)
+        {
+          switch (config_file_vars[num].type)
+            {
+              case CONFIG_CHECKBOX:
+                *(int *) config_file_vars[num].var =
+                      GTK_TOGGLE_BUTTON (config_file_vars[num].widget)->active;
+                break;
+              case CONFIG_INTTEXT:
+              case CONFIG_UINTTEXT:
+                tempstr = gtk_entry_get_text ( 
+                               GTK_ENTRY (config_file_vars[num].widget));
+                *(int *) config_file_vars[num].var = strtol (tempstr, NULL, 10);
+                break;
+              case CONFIG_FLOATTEXT:
+                tempstr = gtk_entry_get_text ( 
+                               GTK_ENTRY (config_file_vars[num].widget));
+                *(double *) config_file_vars[num].var = strtod (tempstr, NULL);
+                break;
+              case CONFIG_CHARTEXT:
+              case CONFIG_CHARPASS:
+                tempstr = gtk_entry_get_text ( 
+                               GTK_ENTRY (config_file_vars[num].widget));
+                g_free (*(char **) config_file_vars[num].var);
+                *(char **) config_file_vars[num].var = 
+                                                g_malloc (strlen (tempstr) + 1);
+                strcpy (*(char **) config_file_vars[num].var, tempstr);
+                break;
+            }
+        }
+    }
+
+  tempstr = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (def_proto_combo)->entry));
+  found = 0;
+  for (i = 0; gftp_protocols[i].name; i++)
+    {
+      if (strcmp (gftp_protocols[i].name, tempstr) == 0)
+        {
+          found = 1;
+          break;
+        }
+    }
+
+  if (found)
+    {
+      g_free (default_protocol);
+      default_protocol = g_strconcat (tempstr, NULL);
+    }
+
+  templist = proxy_hosts;
+  proxy_hosts = new_proxy_hosts;
+  new_proxy_hosts = templist;
+  clean_old_changes (NULL, NULL);
+
+  if (proxy_config != NULL)
+    g_free (proxy_config);
+  proxy_config = get_proxy_config ();
+
+  gftp_write_config_file ();
+}
+
+
 #if GTK_MAJOR_VERSION > 1
 static void
 options_action (GtkWidget * widget, gint response, gpointer user_data)
@@ -65,6 +218,502 @@
 #endif
 
 
+static void
+proxy_toggle (GtkList * list, GtkWidget * child, gpointer data)
+{
+  int proxy_num;
+  char *str;
+
+#if GTK_MAJOR_VERSION > 1
+  GtkTextIter iter, iter2;
+  GtkTextBuffer * textbuf;
+  guint len;
+#endif
+
+  proxy_num = gtk_list_child_position (list, child);
+  if (proxy_num == GFTP_CUSTOM_PROXY_NUM)
+    str = custom_proxy;
+  else
+    str = proxy_type[proxy_num].description;
+
+#if GTK_MAJOR_VERSION == 1
+  gtk_text_set_point (GTK_TEXT (proxy_text), 0);
+  gtk_text_forward_delete (GTK_TEXT (proxy_text),
+			   gtk_text_get_length (GTK_TEXT (proxy_text)));
+
+  gtk_text_insert (GTK_TEXT (proxy_text), NULL, NULL, NULL, str, -1);
+#else
+  textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (proxy_text));
+  len = gtk_text_buffer_get_char_count (textbuf);
+  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0);
+  gtk_text_buffer_get_iter_at_offset (textbuf, &iter2, len - 1);
+  gtk_text_buffer_delete (textbuf, &iter, &iter2);
+
+  len = gtk_text_buffer_get_char_count (textbuf);
+  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, len - 1);
+  gtk_text_buffer_insert (textbuf, &iter, str, -1);
+#endif
+}
+
+
+static void
+add_host_to_listbox (GList * templist)
+{
+  gftp_proxy_hosts *hosts;
+  char *add_data[2];
+  int num;
+
+  hosts = templist->data;
+  if (hosts->domain)
+    {
+      add_data[0] = hosts->domain;
+      add_data[1] = NULL;
+      num = gtk_clist_append (GTK_CLIST (proxy_list), add_data);
+    }
+  else
+    {
+      add_data[0] = g_strdup_printf ("%d.%d.%d.%d",
+				     hosts->ipv4_network_address >> 24 & 0xff,
+				     hosts->ipv4_network_address >> 16 & 0xff,
+				     hosts->ipv4_network_address >> 8 & 0xff,
+				     hosts->ipv4_network_address & 0xff);
+      add_data[1] = g_strdup_printf ("%d.%d.%d.%d",
+				     hosts->ipv4_netmask >> 24 & 0xff,
+				     hosts->ipv4_netmask >> 16 & 0xff,
+				     hosts->ipv4_netmask >> 8 & 0xff,
+				     hosts->ipv4_netmask & 0xff);
+      num = gtk_clist_append (GTK_CLIST (proxy_list), add_data);
+      g_free (add_data[0]);
+      g_free (add_data[1]);
+    }
+  gtk_clist_set_row_data (GTK_CLIST (proxy_list), num, (gpointer) templist);
+}
+
+
+static void
+add_ok (GtkWidget * widget, gpointer data)
+{
+  gftp_proxy_hosts *hosts;
+  const char *edttxt;
+  GList *templist;
+  int num;
+
+  if ((templist = data) == NULL)
+    {
+      hosts = g_malloc0 (sizeof (*hosts));
+      new_proxy_hosts = g_list_append (new_proxy_hosts, hosts);
+      for (templist = new_proxy_hosts; templist->next != NULL;
+	   templist = templist->next);
+    }
+  else
+    {
+      num = gtk_clist_find_row_from_data (GTK_CLIST (proxy_list), templist);
+      if (num != -1)
+	gtk_clist_remove (GTK_CLIST (proxy_list), num);
+      hosts = templist->data;
+    }
+
+  if (hosts->domain)
+    {
+      g_free (hosts->domain);
+      hosts->domain = NULL;
+    }
+
+  if (GTK_TOGGLE_BUTTON (domain_active)->active)
+    {
+      edttxt = gtk_entry_get_text (GTK_ENTRY (new_proxy_domain));
+      hosts->domain = g_malloc (strlen (edttxt) + 1);
+      strcpy (hosts->domain, edttxt);
+      hosts->ipv4_netmask = hosts->ipv4_network_address = 0;
+    }
+  else
+    {
+      edttxt = gtk_entry_get_text (GTK_ENTRY (network1));
+      hosts->ipv4_network_address = (strtol (edttxt, NULL, 10) & 0xff) << 24;
+
+      edttxt = gtk_entry_get_text (GTK_ENTRY (network2));
+      hosts->ipv4_network_address |= (strtol (edttxt, NULL, 10) & 0xff) << 16;
+
+      edttxt = gtk_entry_get_text (GTK_ENTRY (network3));
+      hosts->ipv4_network_address |= (strtol (edttxt, NULL, 10) & 0xff) << 8;
+
+      edttxt = gtk_entry_get_text (GTK_ENTRY (network4));
+      hosts->ipv4_network_address |= strtol (edttxt, NULL, 10) & 0xff;
+
+      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask1));
+      hosts->ipv4_netmask = (strtol (edttxt, NULL, 10) & 0xff) << 24;
+
+      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask2));
+      hosts->ipv4_netmask |= (strtol (edttxt, NULL, 10) & 0xff) << 16;
+
+      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask3));
+      hosts->ipv4_netmask |= (strtol (edttxt, NULL, 10) & 0xff) << 8;
+
+      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask4));
+      hosts->ipv4_netmask |= strtol (edttxt, NULL, 10) & 0xff;
+    }
+  add_host_to_listbox (templist);
+}
+
+
+#if GTK_MAJOR_VERSION > 1
+static void
+proxyhosts_action (GtkWidget * widget, gint response, gpointer user_data)
+{
+  switch (response)
+    {
+      case GTK_RESPONSE_OK:
+        add_ok (widget, user_data);
+        /* no break */
+      default:
+        gtk_widget_destroy (widget);
+    }
+}
+#endif
+
+
+static void
+add_toggle (GtkWidget * widget, gpointer data)
+{
+  gtk_widget_set_sensitive (new_proxy_domain, data != NULL);
+  gtk_widget_set_sensitive (network1, data == NULL);
+  gtk_widget_set_sensitive (network2, data == NULL);
+  gtk_widget_set_sensitive (network3, data == NULL);
+  gtk_widget_set_sensitive (network4, data == NULL);
+  gtk_widget_set_sensitive (netmask1, data == NULL);
+  gtk_widget_set_sensitive (netmask2, data == NULL);
+  gtk_widget_set_sensitive (netmask3, data == NULL);
+  gtk_widget_set_sensitive (netmask4, data == NULL);
+}
+
+
+static void
+delete_proxy_host (GtkWidget * widget, gpointer data)
+{
+  GList *templist;
+  int num;
+
+  if ((templist = GTK_CLIST (proxy_list)->selection) == NULL)
+    return;
+  num = (int) templist->data;
+  templist = gtk_clist_get_row_data (GTK_CLIST (proxy_list), num);
+  new_proxy_hosts = g_list_remove_link (new_proxy_hosts, templist);
+  gtk_clist_remove (GTK_CLIST (proxy_list), num);
+}
+
+
+static void
+add_proxy_host (GtkWidget * widget, gpointer data)
+{
+  GtkWidget *tempwid, *dialog, *frame, *box, *table;
+  gftp_proxy_hosts *hosts;
+  char *tempstr, *title;
+  GList *templist;
+
+  if (data)
+    {
+      if ((templist = GTK_CLIST (proxy_list)->selection) == NULL)
+	return;
+      templist = gtk_clist_get_row_data (GTK_CLIST (proxy_list), 
+                                         (int) templist->data);
+      hosts = templist->data;
+    }
+  else
+    {
+      hosts = NULL;
+      templist = NULL;
+    }
+
+  title = hosts ? _("Edit Host") : _("Add Host");
+#if GTK_MAJOR_VERSION == 1
+  dialog = gtk_dialog_new ();
+  gtk_window_set_title (GTK_WINDOW (dialog), title);
+  gtk_container_border_width (GTK_CONTAINER
+			      (GTK_DIALOG (dialog)->action_area), 5);
+  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 15);
+  gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->action_area), TRUE);
+  gtk_grab_add (dialog);
+#else
+  dialog = gtk_dialog_new_with_buttons (title, NULL, 0,
+                                        GTK_STOCK_SAVE,
+                                        GTK_RESPONSE_OK,
+                                        GTK_STOCK_CANCEL,
+                                        GTK_RESPONSE_CANCEL,
+                                        NULL);
+#endif
+  gtk_container_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 10);
+  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
+  gtk_window_set_wmclass (GTK_WINDOW(dialog), "hostinfo", "Gftp");
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  frame = gtk_frame_new (NULL);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE,
+		      0);
+  gtk_widget_show (frame);
+
+  box = gtk_hbox_new (FALSE, 5);
+  gtk_container_border_width (GTK_CONTAINER (box), 5);
+  gtk_container_add (GTK_CONTAINER (frame), box);
+  gtk_widget_show (box);
+
+  tempwid = gtk_label_new (_("Domain"));
+  gtk_box_pack_start (GTK_BOX (box), tempwid, TRUE, TRUE, 0);
+  gtk_widget_show (tempwid);
+
+  new_proxy_domain = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (box), new_proxy_domain, TRUE, TRUE, 0);
+  gtk_widget_show (new_proxy_domain);
+
+  frame = gtk_frame_new (NULL);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE,
+		      0);
+  gtk_widget_show (frame);
+
+  table = gtk_table_new (4, 2, FALSE);
+  gtk_container_border_width (GTK_CONTAINER (table), 5);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  tempwid = gtk_label_new (_("Network Address"));
+  gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 0, 1);
+  gtk_widget_show (tempwid);
+
+  box = gtk_hbox_new (FALSE, 5);
+  gtk_table_attach_defaults (GTK_TABLE (table), box, 1, 2, 0, 1);
+  gtk_widget_show (box);
+
+  network1 = gtk_entry_new ();
+  gtk_widget_set_size_request (network1, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), network1, TRUE, TRUE, 0);
+  gtk_widget_show (network1);
+
+  network2 = gtk_entry_new ();
+  gtk_widget_set_size_request (network2, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), network2, TRUE, TRUE, 0);
+  gtk_widget_show (network2);
+
+  network3 = gtk_entry_new ();
+  gtk_widget_set_size_request (network3, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), network3, TRUE, TRUE, 0);
+  gtk_widget_show (network3);
+
+  network4 = gtk_entry_new ();
+  gtk_widget_set_size_request (network4, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), network4, TRUE, TRUE, 0);
+  gtk_widget_show (network4);
+
+  tempwid = gtk_label_new (_("Netmask"));
+  gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 1, 2);
+  gtk_widget_show (tempwid);
+
+  box = gtk_hbox_new (FALSE, 5);
+  gtk_table_attach_defaults (GTK_TABLE (table), box, 1, 2, 1, 2);
+  gtk_widget_show (box);
+
+  netmask1 = gtk_entry_new ();
+  gtk_widget_set_size_request (netmask1, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), netmask1, TRUE, TRUE, 0);
+  gtk_widget_show (netmask1);
+
+  netmask2 = gtk_entry_new ();
+  gtk_widget_set_size_request (netmask2, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), netmask2, TRUE, TRUE, 0);
+  gtk_widget_show (netmask2);
+
+  netmask3 = gtk_entry_new ();
+  gtk_widget_set_size_request (netmask3, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), netmask3, TRUE, TRUE, 0);
+  gtk_widget_show (netmask3);
+
+  netmask4 = gtk_entry_new ();
+  gtk_widget_set_size_request (netmask4, 28, -1);
+
+  gtk_box_pack_start (GTK_BOX (box), netmask4, TRUE, TRUE, 0);
+  gtk_widget_show (netmask4);
+
+  box = gtk_hbox_new (FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), box, TRUE, TRUE,
+		      0);
+  gtk_widget_show (box);
+
+  domain_active = gtk_radio_button_new_with_label (NULL, _("Domain"));
+  gtk_signal_connect (GTK_OBJECT (domain_active), "toggled",
+		      GTK_SIGNAL_FUNC (add_toggle), (gpointer) 1);
+  gtk_box_pack_start (GTK_BOX (box), domain_active, TRUE, TRUE, 0);
+  gtk_widget_show (domain_active);
+
+  tempwid = gtk_radio_button_new_with_label (gtk_radio_button_group
+				     (GTK_RADIO_BUTTON (domain_active)),
+				     _("Network"));
+  gtk_signal_connect (GTK_OBJECT (tempwid), "toggled",
+		      GTK_SIGNAL_FUNC (add_toggle), NULL);
+  gtk_box_pack_start (GTK_BOX (box), tempwid, TRUE, TRUE, 0);
+  gtk_widget_show (tempwid);
+
+  if (!hosts || !hosts->domain)
+    {
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tempwid), TRUE);
+      add_toggle (NULL, NULL);
+    }
+  else
+    {
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (domain_active), TRUE);
+      add_toggle (NULL, (gpointer) 1);
+    }
+
+  if (hosts)
+    {
+      if (hosts->domain)
+        gtk_entry_set_text (GTK_ENTRY (new_proxy_domain), hosts->domain);
+      else
+	{
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address >> 24 & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (network1), tempstr);
+	  g_free (tempstr);
+
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address >> 16 & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (network2), tempstr);
+	  g_free (tempstr);
+
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address >> 8 & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (network3), tempstr);
+	  g_free (tempstr);
+
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (network4), tempstr);
+	  g_free (tempstr);
+
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask >> 24 & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (netmask1), tempstr);
+	  g_free (tempstr);
+
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask >> 16 & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (netmask2), tempstr);
+	  g_free (tempstr);
+
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask >> 8 & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (netmask3), tempstr);
+	  g_free (tempstr);
+
+	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask & 0xff);
+	  gtk_entry_set_text (GTK_ENTRY (netmask4), tempstr);
+	  g_free (tempstr);
+	}
+    }
+
+#if GTK_MAJOR_VERSION == 1
+  tempwid = gtk_button_new_with_label (_("OK"));
+  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
+		      TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
+		      GTK_SIGNAL_FUNC (add_ok), (gpointer) templist);
+  gtk_signal_connect_object (GTK_OBJECT (tempwid), "clicked",
+			     GTK_SIGNAL_FUNC (gtk_widget_destroy),
+			     GTK_OBJECT (dialog));
+  gtk_widget_show (tempwid);
+
+  tempwid = gtk_button_new_with_label (_("  Cancel  "));
+  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
+		      TRUE, TRUE, 0);
+  gtk_signal_connect_object (GTK_OBJECT (tempwid), "clicked",
+			     GTK_SIGNAL_FUNC (gtk_widget_destroy),
+			     GTK_OBJECT (dialog));
+  gtk_widget_show (tempwid);
+#else
+  g_signal_connect (GTK_OBJECT (dialog), "response",
+                    G_CALLBACK (proxyhosts_action), NULL);
+#endif
+
+  gtk_widget_show (dialog);
+}
+
+static void
+make_proxy_hosts_tab (GtkWidget * notebook)
+{
+  GtkWidget *tempwid, *box, *hbox, *scroll;
+  gftp_proxy_hosts *hosts, *newhosts;
+  char *add_data[2];
+  GList *templist;
+
+  add_data[0] = _("Network");
+  add_data[1] = _("Netmask");
+
+  box = gtk_vbox_new (FALSE, 5);
+  gtk_container_border_width (GTK_CONTAINER (box), 10);
+  gtk_widget_show (box);
+
+  tempwid = gtk_label_new (_("Local Hosts"));
+  gtk_widget_show (tempwid);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), box, tempwid);
+
+  scroll = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_box_pack_start (GTK_BOX (box), scroll, TRUE, TRUE, 0);
+
+  proxy_list = gtk_clist_new_with_titles (2, add_data);
+  gtk_container_add (GTK_CONTAINER (scroll), proxy_list);
+  gtk_clist_set_column_auto_resize (GTK_CLIST (proxy_list), 0, TRUE);
+  gtk_clist_set_column_auto_resize (GTK_CLIST (proxy_list), 1, TRUE);
+  gtk_widget_show (proxy_list);
+  gtk_widget_show (scroll);
+
+  hbox = gtk_hbox_new (TRUE, 15);
+  gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  tempwid = gtk_button_new_with_label (_("Add"));
+  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (hbox), tempwid, TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
+		      GTK_SIGNAL_FUNC (add_proxy_host), NULL);
+  gtk_widget_show (tempwid);
+
+  tempwid = gtk_button_new_with_label (_("Edit"));
+  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (hbox), tempwid, TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
+		      GTK_SIGNAL_FUNC (add_proxy_host), (gpointer) 1);
+  gtk_widget_show (tempwid);
+
+  tempwid = gtk_button_new_with_label (_("Delete"));
+  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (hbox), tempwid, TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
+		      GTK_SIGNAL_FUNC (delete_proxy_host), NULL);
+  gtk_widget_show (tempwid);
+
+  new_proxy_hosts = NULL;
+  for (templist = proxy_hosts; templist != NULL;
+       templist = templist->next)
+    {
+      hosts = templist->data;
+      newhosts = g_malloc (sizeof (*newhosts));
+      memcpy (newhosts, hosts, sizeof (*newhosts));
+      if (newhosts->domain)
+	{
+	  newhosts->domain = g_malloc (strlen (hosts->domain) + 1);
+	  strcpy (newhosts->domain, hosts->domain);
+	}
+      new_proxy_hosts = g_list_prepend (new_proxy_hosts, newhosts);
+      add_host_to_listbox (new_proxy_hosts);
+    }
+}
+
+
 void
 options_dialog (gpointer data)
 {
@@ -348,671 +997,3 @@
   gtk_widget_show (dialog);
 }
 
-
-static void
-make_proxy_hosts_tab (GtkWidget * notebook)
-{
-  GtkWidget *tempwid, *box, *hbox, *scroll;
-  gftp_proxy_hosts *hosts, *newhosts;
-  char *add_data[2];
-  GList *templist;
-
-  add_data[0] = _("Network");
-  add_data[1] = _("Netmask");
-
-  box = gtk_vbox_new (FALSE, 5);
-  gtk_container_border_width (GTK_CONTAINER (box), 10);
-  gtk_widget_show (box);
-
-  tempwid = gtk_label_new (_("Local Hosts"));
-  gtk_widget_show (tempwid);
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), box, tempwid);
-
-  scroll = gtk_scrolled_window_new (NULL, NULL);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_box_pack_start (GTK_BOX (box), scroll, TRUE, TRUE, 0);
-
-  proxy_list = gtk_clist_new_with_titles (2, add_data);
-  gtk_container_add (GTK_CONTAINER (scroll), proxy_list);
-  gtk_clist_set_column_auto_resize (GTK_CLIST (proxy_list), 0, TRUE);
-  gtk_clist_set_column_auto_resize (GTK_CLIST (proxy_list), 1, TRUE);
-  gtk_widget_show (proxy_list);
-  gtk_widget_show (scroll);
-
-  hbox = gtk_hbox_new (TRUE, 15);
-  gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, FALSE, 0);
-  gtk_widget_show (hbox);
-
-  tempwid = gtk_button_new_with_label (_("Add"));
-  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (hbox), tempwid, TRUE, TRUE, 0);
-  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
-		      GTK_SIGNAL_FUNC (add_proxy_host), NULL);
-  gtk_widget_show (tempwid);
-
-  tempwid = gtk_button_new_with_label (_("Edit"));
-  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (hbox), tempwid, TRUE, TRUE, 0);
-  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
-		      GTK_SIGNAL_FUNC (add_proxy_host), (gpointer) 1);
-  gtk_widget_show (tempwid);
-
-  tempwid = gtk_button_new_with_label (_("Delete"));
-  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (hbox), tempwid, TRUE, TRUE, 0);
-  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
-		      GTK_SIGNAL_FUNC (delete_proxy_host), NULL);
-  gtk_widget_show (tempwid);
-
-  new_proxy_hosts = NULL;
-  for (templist = proxy_hosts; templist != NULL;
-       templist = templist->next)
-    {
-      hosts = templist->data;
-      newhosts = g_malloc (sizeof (*newhosts));
-      memcpy (newhosts, hosts, sizeof (*newhosts));
-      if (newhosts->domain)
-	{
-	  newhosts->domain = g_malloc (strlen (hosts->domain) + 1);
-	  strcpy (newhosts->domain, hosts->domain);
-	}
-      new_proxy_hosts = g_list_prepend (new_proxy_hosts, newhosts);
-      add_host_to_listbox (new_proxy_hosts);
-    }
-}
-
-
-static void
-add_host_to_listbox (GList * templist)
-{
-  gftp_proxy_hosts *hosts;
-  char *add_data[2];
-  int num;
-
-  hosts = templist->data;
-  if (hosts->domain)
-    {
-      add_data[0] = hosts->domain;
-      add_data[1] = NULL;
-      num = gtk_clist_append (GTK_CLIST (proxy_list), add_data);
-    }
-  else
-    {
-      add_data[0] = g_strdup_printf ("%d.%d.%d.%d",
-				     hosts->ipv4_network_address >> 24 & 0xff,
-				     hosts->ipv4_network_address >> 16 & 0xff,
-				     hosts->ipv4_network_address >> 8 & 0xff,
-				     hosts->ipv4_network_address & 0xff);
-      add_data[1] = g_strdup_printf ("%d.%d.%d.%d",
-				     hosts->ipv4_netmask >> 24 & 0xff,
-				     hosts->ipv4_netmask >> 16 & 0xff,
-				     hosts->ipv4_netmask >> 8 & 0xff,
-				     hosts->ipv4_netmask & 0xff);
-      num = gtk_clist_append (GTK_CLIST (proxy_list), add_data);
-      g_free (add_data[0]);
-      g_free (add_data[1]);
-    }
-  gtk_clist_set_row_data (GTK_CLIST (proxy_list), num, (gpointer) templist);
-}
-
-
-#if GTK_MAJOR_VERSION > 1
-static void
-proxyhosts_action (GtkWidget * widget, gint response, gpointer user_data)
-{
-  switch (response)
-    {
-      case GTK_RESPONSE_OK:
-        add_ok (widget, user_data);
-        /* no break */
-      default:
-        gtk_widget_destroy (widget);
-    }
-}
-#endif
-
-
-static void
-add_proxy_host (GtkWidget * widget, gpointer data)
-{
-  GtkWidget *tempwid, *dialog, *frame, *box, *table;
-  gftp_proxy_hosts *hosts;
-  char *tempstr, *title;
-  GList *templist;
-
-  if (data)
-    {
-      if ((templist = GTK_CLIST (proxy_list)->selection) == NULL)
-	return;
-      templist = gtk_clist_get_row_data (GTK_CLIST (proxy_list), 
-                                         (int) templist->data);
-      hosts = templist->data;
-    }
-  else
-    {
-      hosts = NULL;
-      templist = NULL;
-    }
-
-  title = hosts ? _("Edit Host") : _("Add Host");
-#if GTK_MAJOR_VERSION == 1
-  dialog = gtk_dialog_new ();
-  gtk_window_set_title (GTK_WINDOW (dialog), title);
-  gtk_container_border_width (GTK_CONTAINER
-			      (GTK_DIALOG (dialog)->action_area), 5);
-  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 15);
-  gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->action_area), TRUE);
-  gtk_grab_add (dialog);
-#else
-  dialog = gtk_dialog_new_with_buttons (title, NULL, 0,
-                                        GTK_STOCK_SAVE,
-                                        GTK_RESPONSE_OK,
-                                        GTK_STOCK_CANCEL,
-                                        GTK_RESPONSE_CANCEL,
-                                        NULL);
-#endif
-  gtk_container_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 10);
-  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
-  gtk_window_set_wmclass (GTK_WINDOW(dialog), "hostinfo", "Gftp");
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  frame = gtk_frame_new (NULL);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE,
-		      0);
-  gtk_widget_show (frame);
-
-  box = gtk_hbox_new (FALSE, 5);
-  gtk_container_border_width (GTK_CONTAINER (box), 5);
-  gtk_container_add (GTK_CONTAINER (frame), box);
-  gtk_widget_show (box);
-
-  tempwid = gtk_label_new (_("Domain"));
-  gtk_box_pack_start (GTK_BOX (box), tempwid, TRUE, TRUE, 0);
-  gtk_widget_show (tempwid);
-
-  new_proxy_domain = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (box), new_proxy_domain, TRUE, TRUE, 0);
-  gtk_widget_show (new_proxy_domain);
-
-  frame = gtk_frame_new (NULL);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE,
-		      0);
-  gtk_widget_show (frame);
-
-  table = gtk_table_new (4, 2, FALSE);
-  gtk_container_border_width (GTK_CONTAINER (table), 5);
-  gtk_table_set_row_spacings (GTK_TABLE (table), 5);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 5);
-  gtk_container_add (GTK_CONTAINER (frame), table);
-  gtk_widget_show (table);
-
-  tempwid = gtk_label_new (_("Network Address"));
-  gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
-  gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 0, 1);
-  gtk_widget_show (tempwid);
-
-  box = gtk_hbox_new (FALSE, 5);
-  gtk_table_attach_defaults (GTK_TABLE (table), box, 1, 2, 0, 1);
-  gtk_widget_show (box);
-
-  network1 = gtk_entry_new ();
-  gtk_widget_set_size_request (network1, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), network1, TRUE, TRUE, 0);
-  gtk_widget_show (network1);
-
-  network2 = gtk_entry_new ();
-  gtk_widget_set_size_request (network2, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), network2, TRUE, TRUE, 0);
-  gtk_widget_show (network2);
-
-  network3 = gtk_entry_new ();
-  gtk_widget_set_size_request (network3, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), network3, TRUE, TRUE, 0);
-  gtk_widget_show (network3);
-
-  network4 = gtk_entry_new ();
-  gtk_widget_set_size_request (network4, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), network4, TRUE, TRUE, 0);
-  gtk_widget_show (network4);
-
-  tempwid = gtk_label_new (_("Netmask"));
-  gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
-  gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 1, 2);
-  gtk_widget_show (tempwid);
-
-  box = gtk_hbox_new (FALSE, 5);
-  gtk_table_attach_defaults (GTK_TABLE (table), box, 1, 2, 1, 2);
-  gtk_widget_show (box);
-
-  netmask1 = gtk_entry_new ();
-  gtk_widget_set_size_request (netmask1, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), netmask1, TRUE, TRUE, 0);
-  gtk_widget_show (netmask1);
-
-  netmask2 = gtk_entry_new ();
-  gtk_widget_set_size_request (netmask2, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), netmask2, TRUE, TRUE, 0);
-  gtk_widget_show (netmask2);
-
-  netmask3 = gtk_entry_new ();
-  gtk_widget_set_size_request (netmask3, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), netmask3, TRUE, TRUE, 0);
-  gtk_widget_show (netmask3);
-
-  netmask4 = gtk_entry_new ();
-  gtk_widget_set_size_request (netmask4, 28, -1);
-
-  gtk_box_pack_start (GTK_BOX (box), netmask4, TRUE, TRUE, 0);
-  gtk_widget_show (netmask4);
-
-  box = gtk_hbox_new (FALSE, 5);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), box, TRUE, TRUE,
-		      0);
-  gtk_widget_show (box);
-
-  domain_active = gtk_radio_button_new_with_label (NULL, _("Domain"));
-  gtk_signal_connect (GTK_OBJECT (domain_active), "toggled",
-		      GTK_SIGNAL_FUNC (add_toggle), (gpointer) 1);
-  gtk_box_pack_start (GTK_BOX (box), domain_active, TRUE, TRUE, 0);
-  gtk_widget_show (domain_active);
-
-  tempwid = gtk_radio_button_new_with_label (gtk_radio_button_group
-				     (GTK_RADIO_BUTTON (domain_active)),
-				     _("Network"));
-  gtk_signal_connect (GTK_OBJECT (tempwid), "toggled",
-		      GTK_SIGNAL_FUNC (add_toggle), NULL);
-  gtk_box_pack_start (GTK_BOX (box), tempwid, TRUE, TRUE, 0);
-  gtk_widget_show (tempwid);
-
-  if (!hosts || !hosts->domain)
-    {
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tempwid), TRUE);
-      add_toggle (NULL, NULL);
-    }
-  else
-    {
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (domain_active), TRUE);
-      add_toggle (NULL, (gpointer) 1);
-    }
-
-  if (hosts)
-    {
-      if (hosts->domain)
-        gtk_entry_set_text (GTK_ENTRY (new_proxy_domain), hosts->domain);
-      else
-	{
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address >> 24 & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (network1), tempstr);
-	  g_free (tempstr);
-
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address >> 16 & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (network2), tempstr);
-	  g_free (tempstr);
-
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address >> 8 & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (network3), tempstr);
-	  g_free (tempstr);
-
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_network_address & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (network4), tempstr);
-	  g_free (tempstr);
-
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask >> 24 & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (netmask1), tempstr);
-	  g_free (tempstr);
-
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask >> 16 & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (netmask2), tempstr);
-	  g_free (tempstr);
-
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask >> 8 & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (netmask3), tempstr);
-	  g_free (tempstr);
-
-	  tempstr = g_strdup_printf ("%d", hosts->ipv4_netmask & 0xff);
-	  gtk_entry_set_text (GTK_ENTRY (netmask4), tempstr);
-	  g_free (tempstr);
-	}
-    }
-
-#if GTK_MAJOR_VERSION == 1
-  tempwid = gtk_button_new_with_label (_("OK"));
-  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
-		      TRUE, TRUE, 0);
-  gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
-		      GTK_SIGNAL_FUNC (add_ok), (gpointer) templist);
-  gtk_signal_connect_object (GTK_OBJECT (tempwid), "clicked",
-			     GTK_SIGNAL_FUNC (gtk_widget_destroy),
-			     GTK_OBJECT (dialog));
-  gtk_widget_show (tempwid);
-
-  tempwid = gtk_button_new_with_label (_("  Cancel  "));
-  GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
-		      TRUE, TRUE, 0);
-  gtk_signal_connect_object (GTK_OBJECT (tempwid), "clicked",
-			     GTK_SIGNAL_FUNC (gtk_widget_destroy),
-			     GTK_OBJECT (dialog));
-  gtk_widget_show (tempwid);
-#else
-  g_signal_connect (GTK_OBJECT (dialog), "response",
-                    G_CALLBACK (proxyhosts_action), NULL);
-#endif
-
-  gtk_widget_show (dialog);
-}
-
-
-static void
-add_toggle (GtkWidget * widget, gpointer data)
-{
-  gtk_widget_set_sensitive (new_proxy_domain, data != NULL);
-  gtk_widget_set_sensitive (network1, data == NULL);
-  gtk_widget_set_sensitive (network2, data == NULL);
-  gtk_widget_set_sensitive (network3, data == NULL);
-  gtk_widget_set_sensitive (network4, data == NULL);
-  gtk_widget_set_sensitive (netmask1, data == NULL);
-  gtk_widget_set_sensitive (netmask2, data == NULL);
-  gtk_widget_set_sensitive (netmask3, data == NULL);
-  gtk_widget_set_sensitive (netmask4, data == NULL);
-}
-
-
-static void
-add_ok (GtkWidget * widget, gpointer data)
-{
-  gftp_proxy_hosts *hosts;
-  const char *edttxt;
-  GList *templist;
-  int num;
-
-  if ((templist = data) == NULL)
-    {
-      hosts = g_malloc0 (sizeof (*hosts));
-      new_proxy_hosts = g_list_append (new_proxy_hosts, hosts);
-      for (templist = new_proxy_hosts; templist->next != NULL;
-	   templist = templist->next);
-    }
-  else
-    {
-      num = gtk_clist_find_row_from_data (GTK_CLIST (proxy_list), templist);
-      if (num != -1)
-	gtk_clist_remove (GTK_CLIST (proxy_list), num);
-      hosts = templist->data;
-    }
-
-  if (hosts->domain)
-    {
-      g_free (hosts->domain);
-      hosts->domain = NULL;
-    }
-
-  if (GTK_TOGGLE_BUTTON (domain_active)->active)
-    {
-      edttxt = gtk_entry_get_text (GTK_ENTRY (new_proxy_domain));
-      hosts->domain = g_malloc (strlen (edttxt) + 1);
-      strcpy (hosts->domain, edttxt);
-      hosts->ipv4_netmask = hosts->ipv4_network_address = 0;
-    }
-  else
-    {
-      edttxt = gtk_entry_get_text (GTK_ENTRY (network1));
-      hosts->ipv4_network_address = (strtol (edttxt, NULL, 10) & 0xff) << 24;
-
-      edttxt = gtk_entry_get_text (GTK_ENTRY (network2));
-      hosts->ipv4_network_address |= (strtol (edttxt, NULL, 10) & 0xff) << 16;
-
-      edttxt = gtk_entry_get_text (GTK_ENTRY (network3));
-      hosts->ipv4_network_address |= (strtol (edttxt, NULL, 10) & 0xff) << 8;
-
-      edttxt = gtk_entry_get_text (GTK_ENTRY (network4));
-      hosts->ipv4_network_address |= strtol (edttxt, NULL, 10) & 0xff;
-
-      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask1));
-      hosts->ipv4_netmask = (strtol (edttxt, NULL, 10) & 0xff) << 24;
-
-      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask2));
-      hosts->ipv4_netmask |= (strtol (edttxt, NULL, 10) & 0xff) << 16;
-
-      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask3));
-      hosts->ipv4_netmask |= (strtol (edttxt, NULL, 10) & 0xff) << 8;
-
-      edttxt = gtk_entry_get_text (GTK_ENTRY (netmask4));
-      hosts->ipv4_netmask |= strtol (edttxt, NULL, 10) & 0xff;
-    }
-  add_host_to_listbox (templist);
-}
-
-
-static void
-delete_proxy_host (GtkWidget * widget, gpointer data)
-{
-  GList *templist;
-  int num;
-
-  if ((templist = GTK_CLIST (proxy_list)->selection) == NULL)
-    return;
-  num = (int) templist->data;
-  templist = gtk_clist_get_row_data (GTK_CLIST (proxy_list), num);
-  new_proxy_hosts = g_list_remove_link (new_proxy_hosts, templist);
-  gtk_clist_remove (GTK_CLIST (proxy_list), num);
-}
-
-
-static void
-proxy_toggle (GtkList * list, GtkWidget * child, gpointer data)
-{
-  int proxy_num;
-  char *str;
-
-#if GTK_MAJOR_VERSION > 1
-  GtkTextIter iter, iter2;
-  GtkTextBuffer * textbuf;
-  guint len;
-#endif
-
-  proxy_num = gtk_list_child_position (list, child);
-  if (proxy_num == GFTP_CUSTOM_PROXY_NUM)
-    str = custom_proxy;
-  else
-    str = proxy_type[proxy_num].description;
-
-#if GTK_MAJOR_VERSION == 1
-  gtk_text_set_point (GTK_TEXT (proxy_text), 0);
-  gtk_text_forward_delete (GTK_TEXT (proxy_text),
-			   gtk_text_get_length (GTK_TEXT (proxy_text)));
-
-  gtk_text_insert (GTK_TEXT (proxy_text), NULL, NULL, NULL, str, -1);
-#else
-  textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (proxy_text));
-  len = gtk_text_buffer_get_char_count (textbuf);
-  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0);
-  gtk_text_buffer_get_iter_at_offset (textbuf, &iter2, len - 1);
-  gtk_text_buffer_delete (textbuf, &iter, &iter2);
-
-  len = gtk_text_buffer_get_char_count (textbuf);
-  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, len - 1);
-  gtk_text_buffer_insert (textbuf, &iter, str, -1);
-#endif
-}
-
-
-static void
-apply_changes (GtkWidget * widget, gpointer data)
-{
-  const char *tempstr;
-  int num, found, i;
-  GList *templist;
-
-  for (num = 0; config_file_vars[num].var != NULL; num++)
-    {
-      if (config_file_vars[num].widget != NULL)
-        {
-          switch (config_file_vars[num].type)
-            {
-              case CONFIG_CHECKBOX:
-                *(int *) config_file_vars[num].var =
-                      GTK_TOGGLE_BUTTON (config_file_vars[num].widget)->active;
-                break;
-              case CONFIG_INTTEXT:
-              case CONFIG_UINTTEXT:
-                tempstr = gtk_entry_get_text ( 
-                               GTK_ENTRY (config_file_vars[num].widget));
-                *(int *) config_file_vars[num].var = strtol (tempstr, NULL, 10);
-                break;
-              case CONFIG_FLOATTEXT:
-                tempstr = gtk_entry_get_text ( 
-                               GTK_ENTRY (config_file_vars[num].widget));
-                *(double *) config_file_vars[num].var = strtod (tempstr, NULL);
-                break;
-              case CONFIG_CHARTEXT:
-              case CONFIG_CHARPASS:
-                tempstr = gtk_entry_get_text ( 
-                               GTK_ENTRY (config_file_vars[num].widget));
-                g_free (*(char **) config_file_vars[num].var);
-                *(char **) config_file_vars[num].var = 
-                                                g_malloc (strlen (tempstr) + 1);
-                strcpy (*(char **) config_file_vars[num].var, tempstr);
-                break;
-            }
-        }
-    }
-
-  tempstr = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (def_proto_combo)->entry));
-  found = 0;
-  for (i = 0; gftp_protocols[i].name; i++)
-    {
-      if (strcmp (gftp_protocols[i].name, tempstr) == 0)
-        {
-          found = 1;
-          break;
-        }
-    }
-
-  if (found)
-    {
-      g_free (default_protocol);
-      default_protocol = g_strconcat (tempstr, NULL);
-    }
-
-  templist = proxy_hosts;
-  proxy_hosts = new_proxy_hosts;
-  new_proxy_hosts = templist;
-  clean_old_changes (NULL, NULL);
-
-  if (proxy_config != NULL)
-    g_free (proxy_config);
-  proxy_config = get_proxy_config ();
-
-  gftp_write_config_file ();
-}
-
-
-static void
-clean_old_changes (GtkWidget * widget, gpointer data)
-{
-  gftp_proxy_hosts *hosts;
-  GList *templist;
-
-  templist = new_proxy_hosts;
-  while (templist != NULL)
-    {
-      hosts = templist->data;
-      if (hosts->domain)
-        g_free (hosts->domain);
-      g_free (hosts);
-      templist = templist->next;
-    }
-  g_list_free (new_proxy_hosts);
-  new_proxy_hosts = NULL;
-
-  if (custom_proxy != NULL)
-    {
-      g_free (custom_proxy);
-      custom_proxy = NULL;
-    }
-}
-
-
-static char *
-get_proxy_config (void)
-{
-  char *newstr, *oldstr, *pos, *endpos, *textstr;
-  guint len;
-#if GTK_MAJOR_VERSION == 1
-  char tmp[128];
-#else
-  GtkTextBuffer * textbuf;
-  GtkTextIter iter, iter2;
-#endif
-
-  textstr = NULL;
-  newstr = g_malloc (1);
-  *newstr = '\0';
-
-#if GTK_MAJOR_VERSION == 1
-  /*
-     GTK_TEXT uses wchar_t instead of char in environment of multibyte encoding
-     locale (ex Japanese),  so we must convert from wide character 
-     to multibyte charator....   Yasuyuki Furukawa (yasu@on.cs.keio.ac.jp)
-   */
-  if (GTK_TEXT (proxy_text)->use_wchar)
-    {
-      wcstombs (tmp, (wchar_t *) GTK_TEXT (proxy_text)->text.wc,
-                sizeof (tmp));
-      pos = tmp;
-    }
-  else
-    {
-      oldstr = (char *) GTK_TEXT (proxy_text)->text.ch; 
-      len = gtk_text_get_length (GTK_TEXT (proxy_text));
-      textstr = g_malloc (len + 1);
-      strncpy (textstr, oldstr, len);
-      textstr[len] = '\0';
-      pos = textstr;
-    }
-#else
-  textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (proxy_text));
-  len = gtk_text_buffer_get_char_count (textbuf);
-  gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0);
-  gtk_text_buffer_get_iter_at_offset (textbuf, &iter2, len - 1);
-  pos = textstr = gtk_text_buffer_get_text (textbuf, &iter, &iter2, 0);
-#endif
-
-  do
-    {
-      if ((endpos = strchr (pos, '\n')) != NULL)
-        *endpos = '\0';
-      oldstr = newstr;
-      if (endpos != NULL)
-        newstr = g_strconcat (newstr, pos, "%n", NULL);
-      else
-        newstr = g_strconcat (newstr, pos, NULL);
-      g_free (oldstr);
-      if (endpos != NULL)
-        {
-          *endpos = '\n';
-          pos = endpos + 1;
-        }
-    }
-  while (endpos != NULL);
-
-#if GTK_MAJOR_VERSION == 1
-  if (!GTK_TEXT (proxy_text)->use_wchar)
-    g_free (textstr);
-#else
-  g_free (textstr);
-#endif
-
-  return (newstr);
-}
-
--- a/src/gtk/transfer.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/transfer.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,104 +20,53 @@
 #include <gftp-gtk.h>
 static const char cvsid[] = "$Id$";
 
-static void *getdir_thread			( void *data );
-static void *connect_thread 			( void *data );
-static void on_next_transfer 			( gftp_transfer * tdata );
-static void show_transfer 			( gftp_transfer * tdata );
-static void transfer_done 			( GList * node );
-static void create_transfer 			( gftp_transfer * tdata );
-static void update_file_status 			( gftp_transfer * tdata );
-static void trans_selectall 			( GtkWidget * widget, 
-						  gpointer data );
-static void trans_unselectall 			( GtkWidget * widget, 
-						  gpointer data );
-static void overwrite 				( GtkWidget * widget, 
-						  gpointer data );
-static void resume 				( GtkWidget * widget, 
-						  gpointer data );
-static void skip 				( GtkWidget * widget, 
-						  gpointer data );
-static void ok 					( GtkWidget * widget, 
-						  gpointer data );
-static void cancel 				( GtkWidget * widget, 
-						  gpointer data );
-static void gftp_gtk_calc_kbs 			( gftp_transfer * tdata, 
-						  ssize_t num_read );
-static void check_done_process 			( void );
-static void do_upload 				( gftp_viewedit_data * ve_proc,
-						  gftp_dialog_data * ddata );
-static void dont_upload 			( gftp_viewedit_data * ve_proc,
-						  gftp_dialog_data * ddata );
-static void free_edit_data 			( gftp_viewedit_data *ve_proc );
-static int get_status 				( gftp_transfer * tdata, 
-						  ssize_t num_read );
-static void wakeup_main_thread			( gpointer data,
-						  gint source, 
-						  GdkInputCondition condition );
-static gint setup_wakeup_main_thread 		( gftp_request * request );
-static void teardown_wakeup_main_thread 	( gftp_request * request, 
-						  gint handler );
-static mode_t parse_attribs 			( char *attribs );
-static void remove_file 			( char *filename );
-
 static GtkWidget * dialog;
 
-int
-ftp_list_files (gftp_window_data * wdata, int usecache)
+static void 
+wakeup_main_thread (gpointer data, gint source, GdkInputCondition condition)
 {
-  guint handler;
-  void *success;
-
-  gtk_label_set (GTK_LABEL (wdata->hoststxt), _("Receiving file names..."));
-  if (gftp_is_started)
-    fix_display ();
+  gftp_request * request;
+  char c;
+ 
+  request = data; 
+  if (request->wakeup_main_thread[0] > 0)
+    read (request->wakeup_main_thread[0], &c, 1);
+}
 
-  wdata->show_selected = 0;
-  if (wdata->files == NULL)
-    {
-      if (check_reconnect (wdata) < 0)
-        return (0);
 
-      gtk_clist_freeze (GTK_CLIST (wdata->listbox));
-      wdata->request->stopable = 1;
-      if (wdata->request->use_threads)
-        {
-          gtk_widget_set_sensitive (stop_btn, 1);
+static gint
+setup_wakeup_main_thread (gftp_request * request)
+{
+  gint handler;
 
-          handler = setup_wakeup_main_thread (wdata->request);
-          pthread_create (&wdata->tid, NULL, getdir_thread, wdata->request);
-          while (wdata->request->stopable)
-            {
-              GDK_THREADS_LEAVE ();
-#if GTK_MAJOR_VERSION == 1
-              g_main_iteration (TRUE);
-#else
-              g_main_context_iteration (NULL, TRUE);
-#endif
-            }
-          teardown_wakeup_main_thread (wdata->request, handler);
+  if (socketpair (AF_UNIX, SOCK_STREAM, 0, request->wakeup_main_thread) == 0)
+    {
+      /* FIXME - depreciated in GDK 2.0 */
+      handler = gdk_input_add (request->wakeup_main_thread[0], 
+                               GDK_INPUT_READ, wakeup_main_thread, request);
+    }
+  else
+    {
+      request->wakeup_main_thread[0] = 0;
+      request->wakeup_main_thread[1] = 0;
+      handler = 0;
+    }
+  return (handler);
+}
 
-          pthread_join (wdata->tid, &success);
-          gtk_widget_set_sensitive (stop_btn, 0);
-        }
-      else
-        success = getdir_thread (wdata->request);
-      wdata->files = success;
-      gtk_clist_thaw (GTK_CLIST (wdata->listbox));
-      memset (&wdata->tid, 0, sizeof (wdata->tid));
+
+static void
+teardown_wakeup_main_thread (gftp_request * request, gint handler)
+{
+  if (request->wakeup_main_thread[0] > 0 && request->wakeup_main_thread[1] > 0)
+    {
+      /* FIXME - depreciated in GDK 2.0 */
+      gdk_input_remove (handler);
+      close (request->wakeup_main_thread[0]);
+      close (request->wakeup_main_thread[1]);
+      request->wakeup_main_thread[0] = 0;
+      request->wakeup_main_thread[1] = 0;
     }
-  
-  if (wdata->files == NULL || !GFTP_IS_CONNECTED (wdata->request))
-    {
-      disconnect (wdata);
-      return (0);
-    }
-
-  wdata->sorted = 0;
-  sortrows (GTK_CLIST (wdata->listbox), *wdata->sortcol, (gpointer) wdata);
-  if (IS_NONE_SELECTED (wdata))
-    gtk_clist_select_row (GTK_CLIST (wdata->listbox), 0, 0);
-  return (1);
 }
 
 
@@ -214,6 +163,65 @@
 }
 
 
+int
+ftp_list_files (gftp_window_data * wdata, int usecache)
+{
+  guint handler;
+  void *success;
+
+  gtk_label_set (GTK_LABEL (wdata->hoststxt), _("Receiving file names..."));
+  if (gftp_is_started)
+    fix_display ();
+
+  wdata->show_selected = 0;
+  if (wdata->files == NULL)
+    {
+      if (check_reconnect (wdata) < 0)
+        return (0);
+
+      gtk_clist_freeze (GTK_CLIST (wdata->listbox));
+      wdata->request->stopable = 1;
+      if (wdata->request->use_threads)
+        {
+          gtk_widget_set_sensitive (stop_btn, 1);
+
+          handler = setup_wakeup_main_thread (wdata->request);
+          pthread_create (&wdata->tid, NULL, getdir_thread, wdata->request);
+          while (wdata->request->stopable)
+            {
+              GDK_THREADS_LEAVE ();
+#if GTK_MAJOR_VERSION == 1
+              g_main_iteration (TRUE);
+#else
+              g_main_context_iteration (NULL, TRUE);
+#endif
+            }
+          teardown_wakeup_main_thread (wdata->request, handler);
+
+          pthread_join (wdata->tid, &success);
+          gtk_widget_set_sensitive (stop_btn, 0);
+        }
+      else
+        success = getdir_thread (wdata->request);
+      wdata->files = success;
+      gtk_clist_thaw (GTK_CLIST (wdata->listbox));
+      memset (&wdata->tid, 0, sizeof (wdata->tid));
+    }
+  
+  if (wdata->files == NULL || !GFTP_IS_CONNECTED (wdata->request))
+    {
+      disconnect (wdata);
+      return (0);
+    }
+
+  wdata->sorted = 0;
+  sortrows (GTK_CLIST (wdata->listbox), *wdata->sortcol, (gpointer) wdata);
+  if (IS_NONE_SELECTED (wdata))
+    gtk_clist_select_row (GTK_CLIST (wdata->listbox), 0, 0);
+  return (1);
+}
+
+
 static void
 try_connect_again (gftp_request * request, gftp_dialog_data * ddata)
 {
@@ -229,6 +237,63 @@
 }
 
 
+static void *
+connect_thread (void *data)
+{
+  static int conn_num;
+  gftp_request * request;
+  int ret, sj;
+
+  request = data;
+  request->user_data = (void *) 0x1;
+
+  conn_num = 0;
+  if (request->use_threads)
+    {
+      sj = sigsetjmp (jmp_environment, 1);
+      use_jmp_environment = 1;
+    }
+  else
+    sj = 0;
+
+  ret = 0;
+  if (sj != 0)
+    {
+      ret = 0;
+      gftp_disconnect (request);
+    }
+
+  while (sj != 1 && (request->retries == 0 || conn_num < request->retries))
+    {
+      conn_num++;
+      if (request->network_timeout > 0)
+        alarm (request->network_timeout);
+      ret = gftp_connect (request) == 0;
+      alarm (0);
+
+      if (ret)
+        break;
+      else if (request->retries == 0 || conn_num < request->retries)
+        {
+          request->logging_function (gftp_logging_misc, request->user_data,
+                     _("Waiting %d seconds until trying to connect again\n"),
+		     request->sleep_time);
+          alarm (request->sleep_time);
+          pause ();
+        }  
+    }
+
+  if (request->use_threads)
+    use_jmp_environment = 0;
+
+  request->user_data = NULL;
+  request->stopable = 0;
+  if (request->wakeup_main_thread[1] > 0)
+    write (request->wakeup_main_thread[1], " ", 1);
+  return ((void *) ret);
+}
+
+
 int
 ftp_connect (gftp_window_data * wdata, gftp_request * request, int getdir)
 {
@@ -316,63 +381,6 @@
 }
 
 
-static void *
-connect_thread (void *data)
-{
-  static int conn_num;
-  gftp_request * request;
-  int ret, sj;
-
-  request = data;
-  request->user_data = (void *) 0x1;
-
-  conn_num = 0;
-  if (request->use_threads)
-    {
-      sj = sigsetjmp (jmp_environment, 1);
-      use_jmp_environment = 1;
-    }
-  else
-    sj = 0;
-
-  ret = 0;
-  if (sj != 0)
-    {
-      ret = 0;
-      gftp_disconnect (request);
-    }
-
-  while (sj != 1 && (request->retries == 0 || conn_num < request->retries))
-    {
-      conn_num++;
-      if (request->network_timeout > 0)
-        alarm (request->network_timeout);
-      ret = gftp_connect (request) == 0;
-      alarm (0);
-
-      if (ret)
-        break;
-      else if (request->retries == 0 || conn_num < request->retries)
-        {
-          request->logging_function (gftp_logging_misc, request->user_data,
-                     _("Waiting %d seconds until trying to connect again\n"),
-		     request->sleep_time);
-          alarm (request->sleep_time);
-          pause ();
-        }  
-    }
-
-  if (request->use_threads)
-    use_jmp_environment = 0;
-
-  request->user_data = NULL;
-  request->stopable = 0;
-  if (request->wakeup_main_thread[1] > 0)
-    write (request->wakeup_main_thread[1], " ", 1);
-  return ((void *) ret);
-}
-
-
 void 
 get_files (gpointer data)
 {
@@ -544,6 +552,193 @@
 }
 
 
+static void
+gftp_gtk_calc_kbs (gftp_transfer * tdata, ssize_t num_read)
+{
+  unsigned long waitusecs;
+  double difftime, curkbs;
+  gftp_file * tempfle;
+  struct timeval tv;
+  unsigned long toadd;
+
+  gettimeofday (&tv, NULL);
+  pthread_mutex_lock (tdata->statmutex);
+
+  tempfle = tdata->curfle->data;
+  tdata->trans_bytes += num_read;
+  tdata->curtrans += num_read;
+  tdata->stalled = 0;
+
+  difftime = (tv.tv_sec - tdata->starttime.tv_sec) + ((double) (tv.tv_usec - tdata->starttime.tv_usec) / 1000000.0);
+  if (difftime <= 0)
+    tdata->kbs = (double) tdata->trans_bytes / 1024.0;
+  else
+    tdata->kbs = (double) tdata->trans_bytes / 1024.0 / difftime;
+
+  difftime = (tv.tv_sec - tdata->lasttime.tv_sec) + ((double) (tv.tv_usec - tdata->lasttime.tv_usec) / 1000000.0);
+
+  if (difftime <= 0)
+    curkbs = (double) (num_read / 1024.0);
+  else
+    curkbs = (double) (num_read / 1024.0 / difftime);
+
+  if (tdata->fromreq->maxkbs > 0 &&
+      curkbs > tdata->fromreq->maxkbs)
+    {
+      waitusecs = (double) num_read / 1024.0 / tdata->fromreq->maxkbs * 1000000.0 - difftime;
+
+      if (waitusecs > 0)
+        {
+          pthread_mutex_unlock (tdata->statmutex);
+          difftime += ((double) waitusecs / 1000000.0);
+          usleep (waitusecs);
+          pthread_mutex_lock (tdata->statmutex);
+        }
+    }
+
+  /* I don't call gettimeofday (&tdata->lasttime) here because this will use
+     less system resources. This will be close enough for what we need */
+  difftime += tdata->lasttime.tv_usec / 1000000.0;
+  toadd = (long) difftime;
+  difftime -= toadd;
+  tdata->lasttime.tv_sec += toadd;
+  tdata->lasttime.tv_usec = difftime * 1000000.0;
+
+  pthread_mutex_unlock (tdata->statmutex);
+}
+
+
+static int
+get_status (gftp_transfer * tdata, ssize_t num_read)
+{
+  gftp_file * tempfle;
+  struct timeval tv;
+
+  pthread_mutex_lock (tdata->structmutex);
+  if (tdata->curfle == NULL)
+    {
+      pthread_mutex_unlock (tdata->structmutex);
+      return (-1);
+    }
+  tempfle = tdata->curfle->data;
+  pthread_mutex_unlock (tdata->structmutex);
+
+  gftp_disconnect (tdata->fromreq);
+  gftp_disconnect (tdata->toreq);
+  if (num_read < 0 || tdata->skip_file)
+    {
+      if (tdata->fromreq->retries != 0 && tdata->current_file_retries >= tdata->fromreq->retries)
+        {
+          tdata->fromreq->logging_function (gftp_logging_error, 
+                   tdata->fromreq->user_data,
+                   _("Error: Remote site %s disconnected. Max retries reached...giving up\n"),
+                   tdata->fromreq->hostname != NULL ? 
+                         tdata->fromreq->hostname : tdata->toreq->hostname);
+          return (-1);
+        }
+      else
+        {
+          tdata->fromreq->logging_function (gftp_logging_error, 
+                     tdata->fromreq->user_data,
+                     _("Error: Remote site %s disconnected. Will reconnect in %d seconds\n"),
+                     tdata->fromreq->hostname != NULL ? 
+                           tdata->fromreq->hostname : tdata->toreq->hostname, 
+                     tdata->fromreq->sleep_time);
+        }
+
+      while (tdata->fromreq->retries == 0 || 
+             tdata->current_file_retries <= tdata->fromreq->retries)
+        {
+          if (!tdata->skip_file)
+            {
+              tv.tv_sec = tdata->fromreq->sleep_time;
+              tv.tv_usec = 0;
+              select (0, NULL, NULL, NULL, &tv);
+            }
+
+          if (gftp_connect (tdata->fromreq) == 0 &&
+              gftp_connect (tdata->toreq) == 0)
+            {
+              pthread_mutex_lock (tdata->structmutex);
+              tdata->resumed_bytes = tdata->resumed_bytes + tdata->trans_bytes - tdata->curresumed - tdata->curtrans;
+              tdata->trans_bytes = 0;
+              if (tdata->skip_file)
+                {
+                  tdata->total_bytes -= tempfle->size;
+                  tdata->curtrans = 0;
+
+                  tdata->curfle = tdata->curfle->next;
+                  tdata->next_file = 1;
+                  tdata->skip_file = 0;
+                  tdata->cancel = 0;
+                  tdata->fromreq->cancel = 0;
+                  tdata->toreq->cancel = 0;
+                }
+              else
+                {
+                  tempfle->transfer_action = GFTP_TRANS_ACTION_RESUME;
+                  tempfle->startsize = tdata->curtrans + tdata->curresumed;
+                  /* We decrement this here because it will be incremented in 
+                     the loop again */
+                  tdata->curresumed = 0;
+                  tdata->current_file_number--; /* Decrement this because it 
+                                                   will be incremented when we 
+                                                   continue in the loop */
+                }
+              gettimeofday (&tdata->starttime, NULL);
+              pthread_mutex_unlock (tdata->structmutex);
+              return (1);
+            }
+          else
+            tdata->current_file_retries++;
+        }
+    }
+  else if (tdata->cancel)
+    return (-1);
+
+  return (0);
+}
+
+
+static mode_t
+parse_attribs (char *attribs)
+{
+  mode_t mode;
+  int cur;
+
+  cur = 0;
+  if (attribs[1] == 'r')
+    cur += 4;
+  if (attribs[2] == 'w')
+    cur += 2;
+  if (attribs[3] == 'x' ||
+      attribs[3] == 's')
+    cur += 1;
+  mode = cur;
+
+  cur = 0;
+  if (attribs[4] == 'r')
+    cur += 4;
+  if (attribs[5] == 'w')
+    cur += 2;
+  if (attribs[6] == 'x' ||
+      attribs[6] == 's')
+    cur += 1;
+  mode = (mode * 10) + cur;
+
+  cur = 0;
+  if (attribs[7] == 'r')
+    cur += 4;
+  if (attribs[8] == 'w')
+    cur += 2;
+  if (attribs[9] == 'x' ||
+      attribs[9] == 's')
+    cur += 1;
+  mode = (mode * 10) + cur;
+
+  return (mode);
+}
+
 
 void * 
 gftp_gtk_transfer_files (void *data)
@@ -925,70 +1120,126 @@
 }
 
 
-gint
-update_downloads (gpointer data)
+static void
+remove_file (char *filename)
+{
+  if (unlink (filename) == 0)
+    ftp_log (gftp_logging_misc, NULL, _("Successfully removed %s\n"),
+             filename);
+  else
+    ftp_log (gftp_logging_error, NULL,
+             _("Error: Could not remove file %s: %s\n"), filename,
+             g_strerror (errno));
+}
+
+
+static void
+free_edit_data (gftp_viewedit_data * ve_proc)
+{
+  int i;
+
+  if (ve_proc->filename)
+    g_free (ve_proc->filename);
+  if (ve_proc->remote_filename)
+    g_free (ve_proc->remote_filename);
+  for (i = 0; ve_proc->argv[i] != NULL; i++)
+    g_free (ve_proc->argv[i]);
+  g_free (ve_proc->argv);
+  g_free (ve_proc);
+}
+
+
+static void
+dont_upload (gftp_viewedit_data * ve_proc, gftp_dialog_data * ddata)
 {
-  char tempstr[50], temp1str[127];
-  GList * templist, * next;
-  gftp_transfer * tdata;
+  remove_file (ve_proc->filename);
+  free_edit_data (ve_proc);
+}
+
+
+static void
+do_upload (gftp_viewedit_data * ve_proc, gftp_dialog_data * ddata)
+{
+  gftp_file * tempfle;
+  GList * newfile;
 
-  if (file_transfer_logs != NULL)
-    display_cached_logs ();
+  tempfle = g_malloc0 (sizeof (*tempfle));
+  tempfle->destfile = ve_proc->remote_filename;
+  ve_proc->remote_filename = NULL;
+  tempfle->file = ve_proc->filename;
+  ve_proc->filename = NULL;
+  tempfle->done_rm = 1;
+  newfile = g_list_append (NULL, tempfle);
+  add_file_transfer (ve_proc->fromwdata->request, ve_proc->towdata->request,
+                     ve_proc->fromwdata, ve_proc->towdata, newfile, 1);
+  free_edit_data (ve_proc);
+}
+
 
-  if (window2.request->gotbytes != 0)
+static void
+check_done_process (void)
+{
+  gftp_viewedit_data * ve_proc;
+  GList * curdata, *deldata;
+  struct stat st;
+  int ret;
+  char *str;
+  pid_t pid;
+
+  viewedit_process_done = 0;
+  while ((pid = waitpid (-1, &ret, WNOHANG)) > 0)
     {
-      if (window2.request->gotbytes == -1)
-	{
-	  update_window_info ();
-	  window2.request->gotbytes = 0;
-	}
-      else
-	{
-	  insert_commas (window2.request->gotbytes, tempstr, sizeof (tempstr));
-          g_snprintf (temp1str, sizeof (temp1str),
-	              _("Retrieving file names...%s bytes"), tempstr);
-	  gtk_label_set (GTK_LABEL (window2.hoststxt), temp1str);
+      curdata = viewedit_processes;
+      while (curdata != NULL)
+        {
+	  ve_proc = curdata->data;
+          deldata = curdata;
+          curdata = curdata->next;
+	  if (ve_proc->pid == pid)
+	    {
+	      viewedit_processes = g_list_remove_link (viewedit_processes, 
+                                                       deldata);
+	      if (ret != 0)
+		ftp_log (gftp_logging_error, NULL,
+			 _("Error: Child %d returned %d\n"), pid, ret);
+	      else
+		ftp_log (gftp_logging_misc, NULL,
+			 _("Child %d returned successfully\n"), pid);
+
+	      if (!ve_proc->view && !ve_proc->dontupload)
+		{
+		  /* We was editing the file. Upload it */
+		  if (stat (ve_proc->filename, &st) == -1)
+		    ftp_log (gftp_logging_error, NULL,
+		         _("Error: Cannot get information about file %s: %s\n"),
+			 ve_proc->filename, g_strerror (errno));
+		  else if (st.st_mtime == ve_proc->st.st_mtime)
+                    {
+		      ftp_log (gftp_logging_misc, NULL,
+		  	       _("File %s was not changed\n"),
+			       ve_proc->filename);
+                      remove_file (ve_proc->filename);
+                    }
+		  else
+		    {
+		      memcpy (&ve_proc->st, &st, sizeof (ve_proc->st));
+		      str = g_strdup_printf (
+			_("File %s has changed.\nWould you like to upload it?"),
+                        ve_proc->remote_filename);
+
+		      MakeYesNoDialog (_("Edit File"), str, 
+                                       do_upload, ve_proc, 
+                                       dont_upload, ve_proc);
+		      g_free (str);
+		      continue;
+		    }
+		}
+
+              free_edit_data (ve_proc);
+	      continue;
+	    }
 	}
     }
-
-  if (viewedit_process_done)
-    check_done_process ();
-
-  for (templist = file_transfers; templist != NULL;)
-    {
-      tdata = templist->data;
-      if (tdata->ready)
-        {
-          pthread_mutex_lock (tdata->structmutex);
-
-	  if (tdata->next_file)
-	    on_next_transfer (tdata);
-     	  else if (tdata->show) 
-	    show_transfer (tdata);
-	  else if (tdata->done)
-	    {
-	      next = templist->next;
-	      transfer_done (templist);
-	      templist = next;
-	      continue;
-	    }
-
-	  if (tdata->curfle != NULL)
-	    {
-	      if (!tdata->started && start_file_transfers &&
-                  (transfer_in_progress == 0 || !do_one_transfer_at_a_time))
-                create_transfer (tdata);
-
-	      if (tdata->started)
-                update_file_status (tdata);
-	    }
-          pthread_mutex_unlock (tdata->structmutex);
-        }
-      templist = templist->next;
-    }
-
-  gtk_timeout_add (500, update_downloads, NULL);
-  return (0);
 }
 
 
@@ -1331,6 +1582,73 @@
 }
 
 
+gint
+update_downloads (gpointer data)
+{
+  char tempstr[50], temp1str[127];
+  GList * templist, * next;
+  gftp_transfer * tdata;
+
+  if (file_transfer_logs != NULL)
+    display_cached_logs ();
+
+  if (window2.request->gotbytes != 0)
+    {
+      if (window2.request->gotbytes == -1)
+	{
+	  update_window_info ();
+	  window2.request->gotbytes = 0;
+	}
+      else
+	{
+	  insert_commas (window2.request->gotbytes, tempstr, sizeof (tempstr));
+          g_snprintf (temp1str, sizeof (temp1str),
+	              _("Retrieving file names...%s bytes"), tempstr);
+	  gtk_label_set (GTK_LABEL (window2.hoststxt), temp1str);
+	}
+    }
+
+  if (viewedit_process_done)
+    check_done_process ();
+
+  for (templist = file_transfers; templist != NULL;)
+    {
+      tdata = templist->data;
+      if (tdata->ready)
+        {
+          pthread_mutex_lock (tdata->structmutex);
+
+	  if (tdata->next_file)
+	    on_next_transfer (tdata);
+     	  else if (tdata->show) 
+	    show_transfer (tdata);
+	  else if (tdata->done)
+	    {
+	      next = templist->next;
+	      transfer_done (templist);
+	      templist = next;
+	      continue;
+	    }
+
+	  if (tdata->curfle != NULL)
+	    {
+	      if (!tdata->started && start_file_transfers &&
+                  (transfer_in_progress == 0 || !do_one_transfer_at_a_time))
+                create_transfer (tdata);
+
+	      if (tdata->started)
+                update_file_status (tdata);
+	    }
+          pthread_mutex_unlock (tdata->structmutex);
+        }
+      templist = templist->next;
+    }
+
+  gtk_timeout_add (500, update_downloads, NULL);
+  return (0);
+}
+
+
 void
 start_transfer (gpointer data)
 {
@@ -1600,6 +1918,132 @@
 }
 
 
+static void
+trans_selectall (GtkWidget * widget, gpointer data)
+{
+  gftp_transfer * tdata;
+  tdata = data;
+
+  gtk_clist_select_all (GTK_CLIST (tdata->clist));
+}
+
+
+static void
+trans_unselectall (GtkWidget * widget, gpointer data)
+{
+  gftp_transfer * tdata;
+  tdata = data;
+
+  gtk_clist_unselect_all (GTK_CLIST (tdata->clist));
+}
+
+
+static void
+overwrite (GtkWidget * widget, gpointer data)
+{
+  GList * templist, * filelist;
+  gftp_transfer * tdata;
+  gftp_file * tempfle;
+  int curpos;
+
+  tdata = data;
+  curpos = 0;
+  filelist = tdata->files;
+  templist = GTK_CLIST (tdata->clist)->selection;
+  while (templist != NULL)
+    {
+      templist = get_next_selection (templist, &filelist, &curpos);
+      tempfle = filelist->data;
+      tempfle->transfer_action = GFTP_TRANS_ACTION_OVERWRITE;
+      gtk_clist_set_text (GTK_CLIST (tdata->clist), curpos, 3, _("Overwrite"));
+    }
+}
+
+
+static void
+resume (GtkWidget * widget, gpointer data)
+{
+  GList * templist, * filelist;
+  gftp_transfer * tdata;
+  gftp_file * tempfle;
+  int curpos;
+
+  tdata = data;
+  curpos = 0;
+  filelist = tdata->files;
+  templist = GTK_CLIST (tdata->clist)->selection;
+  while (templist != NULL)
+    {
+      templist = get_next_selection (templist, &filelist, &curpos);
+      tempfle = filelist->data;
+      tempfle->transfer_action = GFTP_TRANS_ACTION_RESUME;
+      gtk_clist_set_text (GTK_CLIST (tdata->clist), curpos, 3, _("Resume"));
+    }
+}
+
+
+static void
+skip (GtkWidget * widget, gpointer data)
+{
+  GList * templist, * filelist;
+  gftp_transfer * tdata;
+  gftp_file * tempfle;
+  int curpos;
+
+  tdata = data;
+  curpos = 0;
+  filelist = tdata->files;
+  templist = GTK_CLIST (tdata->clist)->selection;
+  while (templist != NULL)
+    {
+      templist = get_next_selection (templist, &filelist, &curpos);
+      tempfle = filelist->data;
+      tempfle->transfer_action = GFTP_TRANS_ACTION_SKIP;
+      gtk_clist_set_text (GTK_CLIST (tdata->clist), curpos, 3, _("Skip"));
+    }
+}
+
+
+static void
+ok (GtkWidget * widget, gpointer data)
+{
+  gftp_transfer * tdata;
+  gftp_file * tempfle;
+  GList * templist;
+
+  tdata = data;
+  pthread_mutex_lock ((pthread_mutex_t *) tdata->structmutex);
+  for (templist = tdata->files; templist != NULL; templist = templist->next)
+    {
+      tempfle = templist->data;
+      if (tempfle->transfer_action != GFTP_TRANS_ACTION_SKIP)
+        break;
+    }
+
+  if (templist == NULL)
+    {
+      tdata->show = 0; 
+      tdata->ready = tdata->done = 1;
+    }
+  else
+    tdata->show = tdata->ready = 1;
+  pthread_mutex_unlock ((pthread_mutex_t *) tdata->structmutex);
+}
+
+
+static void
+cancel (GtkWidget * widget, gpointer data)
+{
+  gftp_transfer * tdata;
+
+  tdata = data;
+  pthread_mutex_lock ((pthread_mutex_t *) tdata->structmutex);
+  tdata->show = 0;
+  tdata->done = tdata->ready = 1;
+  pthread_mutex_unlock ((pthread_mutex_t *) tdata->structmutex);
+}
+
+
 void
 gftp_gtk_ask_transfer (gftp_transfer * tdata)
 {
@@ -1784,488 +2228,3 @@
   dialog = NULL;
 }
 
-
-static void
-trans_selectall (GtkWidget * widget, gpointer data)
-{
-  gftp_transfer * tdata;
-  tdata = data;
-
-  gtk_clist_select_all (GTK_CLIST (tdata->clist));
-}
-
-
-static void
-trans_unselectall (GtkWidget * widget, gpointer data)
-{
-  gftp_transfer * tdata;
-  tdata = data;
-
-  gtk_clist_unselect_all (GTK_CLIST (tdata->clist));
-}
-
-
-static void
-overwrite (GtkWidget * widget, gpointer data)
-{
-  GList * templist, * filelist;
-  gftp_transfer * tdata;
-  gftp_file * tempfle;
-  int curpos;
-
-  tdata = data;
-  curpos = 0;
-  filelist = tdata->files;
-  templist = GTK_CLIST (tdata->clist)->selection;
-  while (templist != NULL)
-    {
-      templist = get_next_selection (templist, &filelist, &curpos);
-      tempfle = filelist->data;
-      tempfle->transfer_action = GFTP_TRANS_ACTION_OVERWRITE;
-      gtk_clist_set_text (GTK_CLIST (tdata->clist), curpos, 3, _("Overwrite"));
-    }
-}
-
-
-static void
-resume (GtkWidget * widget, gpointer data)
-{
-  GList * templist, * filelist;
-  gftp_transfer * tdata;
-  gftp_file * tempfle;
-  int curpos;
-
-  tdata = data;
-  curpos = 0;
-  filelist = tdata->files;
-  templist = GTK_CLIST (tdata->clist)->selection;
-  while (templist != NULL)
-    {
-      templist = get_next_selection (templist, &filelist, &curpos);
-      tempfle = filelist->data;
-      tempfle->transfer_action = GFTP_TRANS_ACTION_RESUME;
-      gtk_clist_set_text (GTK_CLIST (tdata->clist), curpos, 3, _("Resume"));
-    }
-}
-
-
-static void
-skip (GtkWidget * widget, gpointer data)
-{
-  GList * templist, * filelist;
-  gftp_transfer * tdata;
-  gftp_file * tempfle;
-  int curpos;
-
-  tdata = data;
-  curpos = 0;
-  filelist = tdata->files;
-  templist = GTK_CLIST (tdata->clist)->selection;
-  while (templist != NULL)
-    {
-      templist = get_next_selection (templist, &filelist, &curpos);
-      tempfle = filelist->data;
-      tempfle->transfer_action = GFTP_TRANS_ACTION_SKIP;
-      gtk_clist_set_text (GTK_CLIST (tdata->clist), curpos, 3, _("Skip"));
-    }
-}
-
-
-static void
-ok (GtkWidget * widget, gpointer data)
-{
-  gftp_transfer * tdata;
-  gftp_file * tempfle;
-  GList * templist;
-
-  tdata = data;
-  pthread_mutex_lock ((pthread_mutex_t *) tdata->structmutex);
-  for (templist = tdata->files; templist != NULL; templist = templist->next)
-    {
-      tempfle = templist->data;
-      if (tempfle->transfer_action != GFTP_TRANS_ACTION_SKIP)
-        break;
-    }
-
-  if (templist == NULL)
-    {
-      tdata->show = 0; 
-      tdata->ready = tdata->done = 1;
-    }
-  else
-    tdata->show = tdata->ready = 1;
-  pthread_mutex_unlock ((pthread_mutex_t *) tdata->structmutex);
-}
-
-
-static void
-cancel (GtkWidget * widget, gpointer data)
-{
-  gftp_transfer * tdata;
-
-  tdata = data;
-  pthread_mutex_lock ((pthread_mutex_t *) tdata->structmutex);
-  tdata->show = 0;
-  tdata->done = tdata->ready = 1;
-  pthread_mutex_unlock ((pthread_mutex_t *) tdata->structmutex);
-}
-
-
-static void
-gftp_gtk_calc_kbs (gftp_transfer * tdata, ssize_t num_read)
-{
-  unsigned long waitusecs;
-  double difftime, curkbs;
-  gftp_file * tempfle;
-  struct timeval tv;
-  unsigned long toadd;
-
-  gettimeofday (&tv, NULL);
-  pthread_mutex_lock (tdata->statmutex);
-
-  tempfle = tdata->curfle->data;
-  tdata->trans_bytes += num_read;
-  tdata->curtrans += num_read;
-  tdata->stalled = 0;
-
-  difftime = (tv.tv_sec - tdata->starttime.tv_sec) + ((double) (tv.tv_usec - tdata->starttime.tv_usec) / 1000000.0);
-  if (difftime <= 0)
-    tdata->kbs = (double) tdata->trans_bytes / 1024.0;
-  else
-    tdata->kbs = (double) tdata->trans_bytes / 1024.0 / difftime;
-
-  difftime = (tv.tv_sec - tdata->lasttime.tv_sec) + ((double) (tv.tv_usec - tdata->lasttime.tv_usec) / 1000000.0);
-
-  if (difftime <= 0)
-    curkbs = (double) (num_read / 1024.0);
-  else
-    curkbs = (double) (num_read / 1024.0 / difftime);
-
-  if (tdata->fromreq->maxkbs > 0 &&
-      curkbs > tdata->fromreq->maxkbs)
-    {
-      waitusecs = (double) num_read / 1024.0 / tdata->fromreq->maxkbs * 1000000.0 - difftime;
-
-      if (waitusecs > 0)
-        {
-          pthread_mutex_unlock (tdata->statmutex);
-          difftime += ((double) waitusecs / 1000000.0);
-          usleep (waitusecs);
-          pthread_mutex_lock (tdata->statmutex);
-        }
-    }
-
-  /* I don't call gettimeofday (&tdata->lasttime) here because this will use
-     less system resources. This will be close enough for what we need */
-  difftime += tdata->lasttime.tv_usec / 1000000.0;
-  toadd = (long) difftime;
-  difftime -= toadd;
-  tdata->lasttime.tv_sec += toadd;
-  tdata->lasttime.tv_usec = difftime * 1000000.0;
-
-  pthread_mutex_unlock (tdata->statmutex);
-}
-
-
-static void
-check_done_process (void)
-{
-  gftp_viewedit_data * ve_proc;
-  GList * curdata, *deldata;
-  struct stat st;
-  int ret;
-  char *str;
-  pid_t pid;
-
-  viewedit_process_done = 0;
-  while ((pid = waitpid (-1, &ret, WNOHANG)) > 0)
-    {
-      curdata = viewedit_processes;
-      while (curdata != NULL)
-        {
-	  ve_proc = curdata->data;
-          deldata = curdata;
-          curdata = curdata->next;
-	  if (ve_proc->pid == pid)
-	    {
-	      viewedit_processes = g_list_remove_link (viewedit_processes, 
-                                                       deldata);
-	      if (ret != 0)
-		ftp_log (gftp_logging_error, NULL,
-			 _("Error: Child %d returned %d\n"), pid, ret);
-	      else
-		ftp_log (gftp_logging_misc, NULL,
-			 _("Child %d returned successfully\n"), pid);
-
-	      if (!ve_proc->view && !ve_proc->dontupload)
-		{
-		  /* We was editing the file. Upload it */
-		  if (stat (ve_proc->filename, &st) == -1)
-		    ftp_log (gftp_logging_error, NULL,
-		         _("Error: Cannot get information about file %s: %s\n"),
-			 ve_proc->filename, g_strerror (errno));
-		  else if (st.st_mtime == ve_proc->st.st_mtime)
-                    {
-		      ftp_log (gftp_logging_misc, NULL,
-		  	       _("File %s was not changed\n"),
-			       ve_proc->filename);
-                      remove_file (ve_proc->filename);
-                    }
-		  else
-		    {
-		      memcpy (&ve_proc->st, &st, sizeof (ve_proc->st));
-		      str = g_strdup_printf (
-			_("File %s has changed.\nWould you like to upload it?"),
-                        ve_proc->remote_filename);
-
-		      MakeYesNoDialog (_("Edit File"), str, 
-                                       do_upload, ve_proc, 
-                                       dont_upload, ve_proc);
-		      g_free (str);
-		      continue;
-		    }
-		}
-
-              free_edit_data (ve_proc);
-	      continue;
-	    }
-	}
-    }
-}
-
-
-static void
-do_upload (gftp_viewedit_data * ve_proc, gftp_dialog_data * ddata)
-{
-  gftp_file * tempfle;
-  GList * newfile;
-
-  tempfle = g_malloc0 (sizeof (*tempfle));
-  tempfle->destfile = ve_proc->remote_filename;
-  ve_proc->remote_filename = NULL;
-  tempfle->file = ve_proc->filename;
-  ve_proc->filename = NULL;
-  tempfle->done_rm = 1;
-  newfile = g_list_append (NULL, tempfle);
-  add_file_transfer (ve_proc->fromwdata->request, ve_proc->towdata->request,
-                     ve_proc->fromwdata, ve_proc->towdata, newfile, 1);
-  free_edit_data (ve_proc);
-}
-
-
-static void
-dont_upload (gftp_viewedit_data * ve_proc, gftp_dialog_data * ddata)
-{
-  remove_file (ve_proc->filename);
-  free_edit_data (ve_proc);
-}
-
-
-static void
-free_edit_data (gftp_viewedit_data * ve_proc)
-{
-  int i;
-
-  if (ve_proc->filename)
-    g_free (ve_proc->filename);
-  if (ve_proc->remote_filename)
-    g_free (ve_proc->remote_filename);
-  for (i = 0; ve_proc->argv[i] != NULL; i++)
-    g_free (ve_proc->argv[i]);
-  g_free (ve_proc->argv);
-  g_free (ve_proc);
-}
-
-
-static int
-get_status (gftp_transfer * tdata, ssize_t num_read)
-{
-  gftp_file * tempfle;
-  struct timeval tv;
-
-  pthread_mutex_lock (tdata->structmutex);
-  if (tdata->curfle == NULL)
-    {
-      pthread_mutex_unlock (tdata->structmutex);
-      return (-1);
-    }
-  tempfle = tdata->curfle->data;
-  pthread_mutex_unlock (tdata->structmutex);
-
-  gftp_disconnect (tdata->fromreq);
-  gftp_disconnect (tdata->toreq);
-  if (num_read < 0 || tdata->skip_file)
-    {
-      if (tdata->fromreq->retries != 0 && tdata->current_file_retries >= tdata->fromreq->retries)
-        {
-          tdata->fromreq->logging_function (gftp_logging_error, 
-                   tdata->fromreq->user_data,
-                   _("Error: Remote site %s disconnected. Max retries reached...giving up\n"),
-                   tdata->fromreq->hostname != NULL ? 
-                         tdata->fromreq->hostname : tdata->toreq->hostname);
-          return (-1);
-        }
-      else
-        {
-          tdata->fromreq->logging_function (gftp_logging_error, 
-                     tdata->fromreq->user_data,
-                     _("Error: Remote site %s disconnected. Will reconnect in %d seconds\n"),
-                     tdata->fromreq->hostname != NULL ? 
-                           tdata->fromreq->hostname : tdata->toreq->hostname, 
-                     tdata->fromreq->sleep_time);
-        }
-
-      while (tdata->fromreq->retries == 0 || 
-             tdata->current_file_retries <= tdata->fromreq->retries)
-        {
-          if (!tdata->skip_file)
-            {
-              tv.tv_sec = tdata->fromreq->sleep_time;
-              tv.tv_usec = 0;
-              select (0, NULL, NULL, NULL, &tv);
-            }
-
-          if (gftp_connect (tdata->fromreq) == 0 &&
-              gftp_connect (tdata->toreq) == 0)
-            {
-              pthread_mutex_lock (tdata->structmutex);
-              tdata->resumed_bytes = tdata->resumed_bytes + tdata->trans_bytes - tdata->curresumed - tdata->curtrans;
-              tdata->trans_bytes = 0;
-              if (tdata->skip_file)
-                {
-                  tdata->total_bytes -= tempfle->size;
-                  tdata->curtrans = 0;
-
-                  tdata->curfle = tdata->curfle->next;
-                  tdata->next_file = 1;
-                  tdata->skip_file = 0;
-                  tdata->cancel = 0;
-                  tdata->fromreq->cancel = 0;
-                  tdata->toreq->cancel = 0;
-                }
-              else
-                {
-                  tempfle->transfer_action = GFTP_TRANS_ACTION_RESUME;
-                  tempfle->startsize = tdata->curtrans + tdata->curresumed;
-                  /* We decrement this here because it will be incremented in 
-                     the loop again */
-                  tdata->curresumed = 0;
-                  tdata->current_file_number--; /* Decrement this because it 
-                                                   will be incremented when we 
-                                                   continue in the loop */
-                }
-              gettimeofday (&tdata->starttime, NULL);
-              pthread_mutex_unlock (tdata->structmutex);
-              return (1);
-            }
-          else
-            tdata->current_file_retries++;
-        }
-    }
-  else if (tdata->cancel)
-    return (-1);
-
-  return (0);
-}
-
-
-static void 
-wakeup_main_thread (gpointer data, gint source, GdkInputCondition condition)
-{
-  gftp_request * request;
-  char c;
- 
-  request = data; 
-  if (request->wakeup_main_thread[0] > 0)
-    read (request->wakeup_main_thread[0], &c, 1);
-}
-
-
-static gint
-setup_wakeup_main_thread (gftp_request * request)
-{
-  gint handler;
-
-  if (socketpair (AF_UNIX, SOCK_STREAM, 0, request->wakeup_main_thread) == 0)
-    {
-      /* FIXME - depreciated in GDK 2.0 */
-      handler = gdk_input_add (request->wakeup_main_thread[0], 
-                               GDK_INPUT_READ, wakeup_main_thread, request);
-    }
-  else
-    {
-      request->wakeup_main_thread[0] = 0;
-      request->wakeup_main_thread[1] = 0;
-      handler = 0;
-    }
-  return (handler);
-}
-
-
-static void
-teardown_wakeup_main_thread (gftp_request * request, gint handler)
-{
-  if (request->wakeup_main_thread[0] > 0 && request->wakeup_main_thread[1] > 0)
-    {
-      /* FIXME - depreciated in GDK 2.0 */
-      gdk_input_remove (handler);
-      close (request->wakeup_main_thread[0]);
-      close (request->wakeup_main_thread[1]);
-      request->wakeup_main_thread[0] = 0;
-      request->wakeup_main_thread[1] = 0;
-    }
-}
-
-
-static mode_t
-parse_attribs (char *attribs)
-{
-  mode_t mode;
-  int cur;
-
-  cur = 0;
-  if (attribs[1] == 'r')
-    cur += 4;
-  if (attribs[2] == 'w')
-    cur += 2;
-  if (attribs[3] == 'x' ||
-      attribs[3] == 's')
-    cur += 1;
-  mode = cur;
-
-  cur = 0;
-  if (attribs[4] == 'r')
-    cur += 4;
-  if (attribs[5] == 'w')
-    cur += 2;
-  if (attribs[6] == 'x' ||
-      attribs[6] == 's')
-    cur += 1;
-  mode = (mode * 10) + cur;
-
-  cur = 0;
-  if (attribs[7] == 'r')
-    cur += 4;
-  if (attribs[8] == 'w')
-    cur += 2;
-  if (attribs[9] == 'x' ||
-      attribs[9] == 's')
-    cur += 1;
-  mode = (mode * 10) + cur;
-
-  return (mode);
-}
-
-
-static void
-remove_file (char *filename)
-{
-  if (unlink (filename) == 0)
-    ftp_log (gftp_logging_misc, NULL, _("Successfully removed %s\n"),
-             filename);
-  else
-    ftp_log (gftp_logging_error, NULL,
-             _("Error: Could not remove file %s: %s\n"), filename,
-             g_strerror (errno));
-}
-
--- a/src/gtk/view_dialog.c	Tue Nov 05 20:36:11 2002 +0000
+++ b/src/gtk/view_dialog.c	Wed Nov 06 02:20:25 2002 +0000
@@ -20,15 +20,6 @@
 #include "gftp-gtk.h"
 static const char cvsid[] = "$Id$";
 
-static gftp_viewedit_data * fork_process 	( char *proc, 
-						  char *filename,
-						  int fd,
-						  char *remote_filename,
-						  int viewedit, 
-                                                  int del_file,
-                                                  int dontupload,
-						  gftp_window_data * wdata );
-
 static gftp_file * curfle;
 
 void
@@ -162,6 +153,81 @@
 }
 
 
+static gftp_viewedit_data *
+fork_process (char *proc, char *filename, int fd, char *remote_filename, 
+              int viewedit, int del_file, int dontupload, 
+              gftp_window_data * wdata)
+{
+  gftp_viewedit_data * newproc;
+  char *pos, *endpos, **argv;
+  pid_t ret;
+  int n;
+
+  argv = NULL;
+  n = 0;
+  pos = proc;
+  while ((endpos = strchr (pos, ' ')) != NULL)
+    {
+      *endpos = '\0';
+      n++;
+      argv = g_realloc (argv, n * sizeof (char *));
+      argv[n - 1] = g_malloc (strlen (pos) + 1);
+      strcpy (argv[n - 1], pos);
+      *endpos = ' ';
+      pos = endpos + 1;
+    }
+  argv = g_realloc (argv, (n + 3) * sizeof (char *));
+  argv[n] = g_malloc (strlen (pos) + 1);
+  strcpy (argv[n], pos);
+  argv[n + 1] = g_malloc (strlen (filename) + 1);
+  strcpy (argv[n + 1], filename);
+  argv[n + 2] = NULL;
+
+  newproc = NULL;
+  switch ((ret = fork ()))
+    {
+    case 0:
+      close (fd);
+      execvp (argv[0], argv);
+      _exit (1);
+    case -1:
+      for (n = 0; argv[n] != NULL; n++)
+	g_free (argv[n]);
+      ftp_log (gftp_logging_error, NULL,
+              _("View: Cannot fork another process: %s\n"), g_strerror (errno));
+      break;
+    default:
+      ftp_log (gftp_logging_misc, NULL, _("Running program: %s %s\n"), proc,
+	       filename);
+      newproc = g_malloc0 (sizeof (*newproc));
+      newproc->pid = ret;
+      newproc->argv = argv;
+      if (wdata == &window2)
+        {
+          newproc->fromwdata = &window2;
+          newproc->towdata = &window1;
+        }
+      else
+        {
+          newproc->fromwdata = &window1;
+          newproc->towdata = &window2;
+        }
+      newproc->filename = g_malloc (strlen (filename) + 1);
+      strcpy (newproc->filename, filename);
+      if (remote_filename != NULL)
+	{
+	  newproc->remote_filename = g_malloc (strlen (remote_filename) + 1);
+	  strcpy (newproc->remote_filename, remote_filename);
+	}
+      newproc->view = viewedit;
+      newproc->rm = del_file;
+      newproc->dontupload = dontupload;
+      viewedit_processes = g_list_append (viewedit_processes, newproc);
+    }
+  return (newproc);
+}
+
+
 void
 view_file (char *filename, int fd, int viewedit, int del_file, int start_pos,
 	   int dontupload, char *remote_filename, gftp_window_data * wdata)
@@ -348,78 +414,3 @@
     gtk_adjustment_set_value (vadj, vadj->upper);
 }
 
-
-static gftp_viewedit_data *
-fork_process (char *proc, char *filename, int fd, char *remote_filename, 
-              int viewedit, int del_file, int dontupload, 
-              gftp_window_data * wdata)
-{
-  gftp_viewedit_data * newproc;
-  char *pos, *endpos, **argv;
-  pid_t ret;
-  int n;
-
-  argv = NULL;
-  n = 0;
-  pos = proc;
-  while ((endpos = strchr (pos, ' ')) != NULL)
-    {
-      *endpos = '\0';
-      n++;
-      argv = g_realloc (argv, n * sizeof (char *));
-      argv[n - 1] = g_malloc (strlen (pos) + 1);
-      strcpy (argv[n - 1], pos);
-      *endpos = ' ';
-      pos = endpos + 1;
-    }
-  argv = g_realloc (argv, (n + 3) * sizeof (char *));
-  argv[n] = g_malloc (strlen (pos) + 1);
-  strcpy (argv[n], pos);
-  argv[n + 1] = g_malloc (strlen (filename) + 1);
-  strcpy (argv[n + 1], filename);
-  argv[n + 2] = NULL;
-
-  newproc = NULL;
-  switch ((ret = fork ()))
-    {
-    case 0:
-      close (fd);
-      execvp (argv[0], argv);
-      _exit (1);
-    case -1:
-      for (n = 0; argv[n] != NULL; n++)
-	g_free (argv[n]);
-      ftp_log (gftp_logging_error, NULL,
-              _("View: Cannot fork another process: %s\n"), g_strerror (errno));
-      break;
-    default:
-      ftp_log (gftp_logging_misc, NULL, _("Running program: %s %s\n"), proc,
-	       filename);
-      newproc = g_malloc0 (sizeof (*newproc));
-      newproc->pid = ret;
-      newproc->argv = argv;
-      if (wdata == &window2)
-        {
-          newproc->fromwdata = &window2;
-          newproc->towdata = &window1;
-        }
-      else
-        {
-          newproc->fromwdata = &window1;
-          newproc->towdata = &window2;
-        }
-      newproc->filename = g_malloc (strlen (filename) + 1);
-      strcpy (newproc->filename, filename);
-      if (remote_filename != NULL)
-	{
-	  newproc->remote_filename = g_malloc (strlen (remote_filename) + 1);
-	  strcpy (newproc->remote_filename, remote_filename);
-	}
-      newproc->view = viewedit;
-      newproc->rm = del_file;
-      newproc->dontupload = dontupload;
-      viewedit_processes = g_list_append (viewedit_processes, newproc);
-    }
-  return (newproc);
-}
-