changeset 950:c7d7a081cd9c

2008-03-04 Brian Masney <masneyb@gftp.org> * lib/gftp.h lib/socket-connect.c lib/sockutils.c lib/protocols.c lib/Makefile.am lib/charset-conv.c lib/parse-dir-listing.c - split protocols.c into smaller files. No changes were made to the moved functions.
author masneyb
date Tue, 04 Mar 2008 12:28:40 +0000
parents 9a6571938f89
children 99f8858bbf02
files ChangeLog lib/Makefile.am lib/charset-conv.c lib/gftp.h lib/parse-dir-listing.c lib/protocols.c lib/socket-connect.c lib/sockutils.c
diffstat 8 files changed, 1749 insertions(+), 1653 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Mar 04 12:02:47 2008 +0000
+++ b/ChangeLog	Tue Mar 04 12:28:40 2008 +0000
@@ -1,4 +1,9 @@
 2008-03-04 Brian Masney <masneyb@gftp.org>
+	* lib/gftp.h lib/socket-connect.c lib/sockutils.c lib/protocols.c
+	lib/Makefile.am lib/charset-conv.c lib/parse-dir-listing.c - split
+	protocols.c into smaller files. No changes were made to the moved
+	functions.
+
 	* lib/rfc959.c - removed unneeded FIXME comment
 
 	* lib/ftps.c - removed uncommented code
--- a/lib/Makefile.am	Tue Mar 04 12:02:47 2008 +0000
+++ b/lib/Makefile.am	Tue Mar 04 12:28:40 2008 +0000
@@ -2,8 +2,9 @@
 
 SUBDIRS=fsplib
 noinst_LIBRARIES = libgftp.a
-libgftp_a_SOURCES=bookmark.c cache.c config_file.c fsp.c ftps.c https.c \
-                  local.c misc.c mkstemps.c protocols.c pty.c rfc959.c \
-                  rfc2068.c sshv2.c sslcommon.c
+libgftp_a_SOURCES=bookmark.c cache.c charset-conv.c config_file.c fsp.c ftps.c \
+                  https.c local.c misc.c mkstemps.c parse-dir-listing.c \
+                  protocols.c pty.c rfc959.c rfc2068.c sshv2.c sslcommon.c \
+                  socket-connect.c sockutils.c
 INCLUDES=@GLIB_CFLAGS@ @PTHREAD_CFLAGS@ -I../intl -DSHARE_DIR=\"$(datadir)/gftp\" -DLOCALE_DIR=\"$(datadir)/locale\"
 noinst_HEADERS=gftp.h ftpcommon.h httpcommon.h options.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/charset-conv.c	Tue Mar 04 12:28:40 2008 +0000
@@ -0,0 +1,263 @@
+/*****************************************************************************/
+/*  charset-conv.c - contains functions for performing conversions between   */
+/*     character sets.                                                       */
+/*  Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org>                  */
+/*                                                                           */
+/*  This program is free software; you can redistribute it and/or modify     */
+/*  it under the terms of the GNU General Public License as published by     */
+/*  the Free Software Foundation; either version 2 of the License, or        */
+/*  (at your option) any later version.                                      */
+/*                                                                           */
+/*  This program is distributed in the hope that it will be useful,          */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/*  GNU General Public License for more details.                             */
+/*                                                                           */
+/*  You should have received a copy of the GNU General Public License        */
+/*  along with this program; if not, write to the Free Software              */
+/*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+#if GLIB_MAJOR_VERSION > 1
+
+static /*@null@*/ char *
+_gftp_get_next_charset (char **curpos)
+{
+  char *ret, *endpos;
+  size_t len, retlen;
+
+  if (**curpos == '\0')
+    return (NULL);
+
+  for (; **curpos == ' ' || **curpos == '\t'; (*curpos)++);
+
+  if ((endpos = strchr (*curpos, ',')) == NULL)
+    len = strlen (*curpos) - 1; /* the trailing ',' should be omitted */
+  else
+    len = endpos - *curpos;
+
+  for (retlen = len - 1;
+       (*curpos)[retlen - 1] == ' ' || (*curpos)[retlen - 1] == '\t';
+       retlen--);
+
+  retlen++; /* Needed due to the len - 1 above... */
+  ret = g_malloc0 (retlen + 1);
+  memcpy (ret, *curpos, retlen);
+
+  for (*curpos += len; **curpos == ','; (*curpos)++);
+
+  return (ret);
+}
+
+
+static void
+_do_show_iconv_error (const char *str, char *charset, int from_utf8,
+                      GError * error)
+{
+  const char *fromset, *toset;
+
+  if (from_utf8)
+    {
+      fromset = "UTF-8";
+      toset = charset;
+    }
+  else
+    {
+      fromset = charset;
+      toset = "UTF-8";
+    }
+
+  printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
+          str, fromset, toset, error->message);
+}
+
+
+/*@null@*/ static char *
+_do_convert_string (gftp_request * request, int is_filename, int force_local,
+                    const char *str, size_t *dest_len, int from_utf8)
+{
+  char *remote_charsets, *ret, *fromset, *toset, *stpos, *cur_charset;
+  GError * error;
+  gsize bread;
+
+  if (request == NULL)
+    return (NULL);
+
+  if (g_utf8_validate (str, -1, NULL) != from_utf8)
+    return (NULL);
+
+  error = NULL;
+  gftp_lookup_request_option (request, "remote_charsets", &remote_charsets);
+  if (*remote_charsets == '\0' || request->use_local_encoding ||
+      force_local == 1)
+    {
+      if (from_utf8)
+        {
+          if (is_filename)
+            ret = g_filename_from_utf8 (str, -1, &bread, dest_len, &error);
+          else
+            ret = g_locale_from_utf8 (str, -1, &bread, dest_len, &error);
+        }
+      else
+        {
+          if (is_filename)
+            ret = g_filename_to_utf8 (str, -1, &bread, dest_len, &error);
+          else
+            ret = g_locale_to_utf8 (str, -1, &bread, dest_len, &error);
+        }
+
+      if (ret == NULL)
+        _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
+
+      return (ret);
+    }
+
+  if (from_utf8)
+    {
+      if (request->iconv_from_initialized)
+        {
+          ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread, dest_len,
+                                      &error);
+          if (ret == NULL)
+            _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
+
+          return (ret);
+        }
+    }
+  else
+    {
+      if (request->iconv_to_initialized)
+        {
+          ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread, dest_len,
+                                      &error);
+          if (ret == NULL)
+            _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
+
+          return (ret);
+        }
+    }
+
+  stpos = remote_charsets;
+  while ((cur_charset = _gftp_get_next_charset (&stpos)) != NULL)
+    {
+      if (from_utf8)
+        {
+          fromset = "UTF-8";
+          toset = cur_charset;
+          if ((request->iconv_from = g_iconv_open (toset, fromset)) == (GIConv) -1)
+            {
+              g_free (cur_charset);
+              continue;
+            }
+
+          error = NULL;
+          if ((ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread,
+                                           dest_len, &error)) == NULL)
+            {
+              g_iconv_close (request->iconv_from);
+              request->iconv_from = NULL;
+              _do_show_iconv_error (str, cur_charset, from_utf8, error);
+              g_free (cur_charset);
+              continue;
+            }
+
+          request->iconv_from_initialized = 1;
+        }
+      else
+        {
+          fromset = cur_charset;
+          toset = "UTF-8";
+          if ((request->iconv_to = g_iconv_open (toset, fromset)) == (GIConv) -1)
+            {
+              g_free (cur_charset);
+              continue;
+            }
+
+          error = NULL;
+          if ((ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread,
+                                           dest_len, &error)) == NULL)
+            {
+              g_iconv_close (request->iconv_to);
+              request->iconv_to = NULL;
+              _do_show_iconv_error (str, cur_charset, from_utf8, error);
+              g_free (cur_charset);
+              continue;
+            }
+
+          request->iconv_to_initialized = 1;
+        }
+
+      request->iconv_charset = cur_charset;
+      return (ret);
+    }
+
+  return (NULL);
+}
+
+char *
+gftp_string_to_utf8 (gftp_request * request, const char *str, size_t *dest_len)
+{
+  return (_do_convert_string (request, 0, 0, str, dest_len, 0));
+}
+
+
+char *
+gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
+                       size_t *dest_len)
+{
+  return (_do_convert_string (request, 0, force_local, str, dest_len, 1));
+}
+
+
+char *
+gftp_filename_to_utf8 (gftp_request * request, const char *str,
+                       size_t *dest_len)
+{
+  return (_do_convert_string (request, 1, 0, str, dest_len, 0));
+}
+
+
+char *
+gftp_filename_from_utf8 (gftp_request * request, const char *str,
+                         size_t *dest_len)
+{
+  return (_do_convert_string (request, 1, 0, str, dest_len, 1));
+}
+
+#else
+
+char *
+gftp_string_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
+{
+  return (NULL);
+}
+
+
+char *
+gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
+                       size_t dest_len)
+{
+  return (NULL);
+}
+
+
+char *
+gftp_filename_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
+{
+  return (NULL);
+}
+
+
+char *
+gftp_filename_from_utf8 (gftp_request * request, int force_local,
+                         const char *str, size_t dest_len)
+{
+  return (NULL);
+}
+
+#endif
+
+
--- a/lib/gftp.h	Tue Mar 04 12:02:47 2008 +0000
+++ b/lib/gftp.h	Tue Mar 04 12:28:40 2008 +0000
@@ -668,6 +668,24 @@
 					  char *descr,
 					  int ignore_directory );
 
+/* charset-conv.c */
+/*@null@*/ char * gftp_string_to_utf8	( gftp_request * request, 
+					  const char *str,
+					  size_t *dest_len );
+
+/*@null@*/ char * gftp_string_from_utf8	( gftp_request * request, 
+					  int force_local,
+					  const char *str,
+					  size_t *dest_len );
+
+/*@null@*/ char * gftp_filename_to_utf8	( gftp_request * request, 
+					  const char *str,
+					  size_t *dest_len );
+
+/*@null@*/ char * gftp_filename_from_utf8 ( gftp_request * request, 
+					  const char *str,
+					  size_t *dest_len );
+
 /* config_file.c */
 int gftp_config_parse_args 		( char *str, 
 					  int numargs, 
@@ -812,6 +830,15 @@
 int mkstemps 				( char *template,
 					  int suffix_len );
 
+/* parse-dir-listing.c */
+time_t parse_time 			( char *str,
+					  char **endpos );
+
+int gftp_parse_ls 			( gftp_request * request,
+					  const char *lsoutput, 
+					  gftp_file *fle,
+					  int fd );
+
 /* protocols.c */
 #define GFTP_FTP_NUM				0
 #define GFTP_FTPS_NUM				1
@@ -909,23 +936,6 @@
 
 int gftp_list_files 			( gftp_request * request );
 
-/*@null@*/ char * gftp_string_to_utf8	( gftp_request * request, 
-					  const char *str,
-					  size_t *dest_len );
-
-/*@null@*/ char * gftp_string_from_utf8	( gftp_request * request, 
-					  int force_local,
-					  const char *str,
-					  size_t *dest_len );
-
-/*@null@*/ char * gftp_filename_to_utf8	( gftp_request * request, 
-					  const char *str,
-					  size_t *dest_len );
-
-/*@null@*/ char * gftp_filename_from_utf8 ( gftp_request * request, 
-					  const char *str,
-					  size_t *dest_len );
-
 int gftp_parse_bookmark 		( gftp_request * request, 
 					  gftp_request * local_request,
 					  const char * bookmark,
@@ -996,23 +1006,10 @@
 void gftp_calc_kbs 			( gftp_transfer * tdata, 
 				 	  ssize_t num_read );
 
-time_t parse_time 			( char *str,
-					  char **endpos );
-
-int gftp_parse_ls 			( gftp_request * request,
-					  const char *lsoutput, 
-					  gftp_file *fle,
-					  int fd );
-
 int gftp_get_all_subdirs 		( gftp_transfer * transfer, 
 					  void (*update_func) 
 						( gftp_transfer * transfer ));
 
-int gftp_connect_server 		( gftp_request * request, 
-					  char *service,
-					  char *proxy_hostname,
-					  unsigned int proxy_port );
-
 struct hostent *r_gethostbyname 	( const char *name, 
 					  struct hostent *result_buf, 
 					  int *h_errnop );
@@ -1026,33 +1023,6 @@
 
 void print_file_list 			( GList * list );
 
-void gftp_free_getline_buffer 		( gftp_getline_buffer ** rbuf );
-
-ssize_t gftp_get_line 			( gftp_request * request, 
-					  /*@out@*/ gftp_getline_buffer ** rbuf,
-					  /*@out@*/ char * str, 
-					  size_t len, 
-					  int fd );
-
-ssize_t gftp_fd_read 			( gftp_request * request, 
-					  void *ptr, 
-					  size_t size, 
-					  int fd );
-
-ssize_t gftp_fd_write 			( gftp_request * request, 
-					  const char *ptr, 
-					  size_t size, 
-					  int fd );
-
-ssize_t gftp_writefmt 			( gftp_request * request, 
-					  int fd, 
-					  const char *fmt, 
-					  ... );
-
-int gftp_fd_set_sockblocking 		( gftp_request * request, 
-					  int fd, 
-					  int non_blocking );
-
 void gftp_swap_socks 			( gftp_request * dest, 
 					  gftp_request * source );
 
@@ -1118,3 +1088,37 @@
 
 #endif
 
+/* socket-connect.c */
+int gftp_connect_server 		( gftp_request * request, 
+					  char *service,
+					  char *proxy_hostname,
+					  unsigned int proxy_port );
+
+/* sockutils.c */
+ssize_t gftp_get_line 			( gftp_request * request, 
+					  /*@out@*/ gftp_getline_buffer ** rbuf,
+					  /*@out@*/ char * str, 
+					  size_t len, 
+					  int fd );
+
+void gftp_free_getline_buffer 		( gftp_getline_buffer ** rbuf );
+
+ssize_t gftp_fd_read 			( gftp_request * request, 
+					  void *ptr, 
+					  size_t size, 
+					  int fd );
+
+ssize_t gftp_fd_write 			( gftp_request * request, 
+					  const char *ptr, 
+					  size_t size, 
+					  int fd );
+
+ssize_t gftp_writefmt 			( gftp_request * request, 
+					  int fd, 
+					  const char *fmt, 
+					  ... );
+
+int gftp_fd_set_sockblocking 		( gftp_request * request, 
+					  int fd, 
+					  int non_blocking );
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/parse-dir-listing.c	Tue Mar 04 12:28:40 2008 +0000
@@ -0,0 +1,655 @@
+/*****************************************************************************/
+/*  parse-dir-listing.c - contains functions for parsing the different types */
+/*     of directory listings.                                                */
+/*  Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org>                  */
+/*                                                                           */
+/*  This program is free software; you can redistribute it and/or modify     */
+/*  it under the terms of the GNU General Public License as published by     */
+/*  the Free Software Foundation; either version 2 of the License, or        */
+/*  (at your option) any later version.                                      */
+/*                                                                           */
+/*  This program is distributed in the hope that it will be useful,          */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/*  GNU General Public License for more details.                             */
+/*                                                                           */
+/*  You should have received a copy of the GNU General Public License        */
+/*  along with this program; if not, write to the Free Software              */
+/*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+static char *
+copy_token (/*@out@*/ char **dest, char *source)
+{
+  char *endpos, savepos;
+
+  endpos = source;
+  while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
+    endpos++;
+  if (*endpos == '\0')
+    {
+      *dest = NULL;
+      return (NULL);
+    }
+
+  savepos = *endpos;
+  *endpos = '\0';
+  *dest = g_malloc0 ((gulong) (endpos - source + 1));
+  strcpy (*dest, source);
+  *endpos = savepos;
+
+  /* Skip the blanks till we get to the next entry */
+  source = endpos + 1;
+  while ((*source == ' ' || *source == '\t') && *source != '\0')
+    source++;
+  return (source);
+}
+
+
+static char *
+goto_next_token (char *pos)
+{
+  while (*pos != ' ' && *pos != '\t' && *pos != '\0')
+    pos++;
+
+  while (*pos == ' ' || *pos == '\t')
+    pos++;
+
+  return (pos);
+}
+
+
+static time_t
+parse_vms_time (char *str, char **endpos)
+{
+  struct tm curtime;
+  time_t ret;
+
+  /* 8-JUN-2004 13:04:14 */
+  memset (&curtime, 0, sizeof (curtime));
+
+  *endpos = strptime (str, "%d-%b-%Y %H:%M:%S", &curtime);
+  if (*endpos == NULL)
+    *endpos = strptime (str, "%d-%b-%Y %H:%M", &curtime);
+  
+  if (*endpos != NULL)
+    {
+      ret = mktime (&curtime);
+      for (; **endpos == ' ' || **endpos == '\t'; (*endpos)++);
+    }
+  else
+    {
+      ret = 0;
+      *endpos = goto_next_token (str);
+      if (*endpos != NULL)
+        *endpos = goto_next_token (*endpos);
+    }
+
+  return (ret);
+}
+
+
+time_t
+parse_time (char *str, char **endpos)
+{
+  struct tm curtime, *loctime;
+  time_t t, ret;
+  char *tmppos;
+  size_t slen;
+  int i, num;
+
+  slen = strlen (str);
+  memset (&curtime, 0, sizeof (curtime));
+  curtime.tm_isdst = -1;
+
+  if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' && 
+      isdigit ((int) str[3]))
+    {
+      /* This is how DOS will return the date/time */
+      /* 07-06-99  12:57PM */
+
+      tmppos = strptime (str, "%m-%d-%y %I:%M%p", &curtime);
+    }
+  else if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' && 
+           isalpha (str[3]))
+    {
+      /* 10-Jan-2003 09:14 */
+      tmppos = strptime (str, "%d-%h-%Y %H:%M", &curtime);
+    }
+  else if (slen > 4 && isdigit ((int) str[0]) && str[4] == '/')
+    {
+      /* 2003/12/25 */
+      tmppos = strptime (str, "%Y/%m/%d", &curtime);
+    }
+  else
+    {
+      /* This is how most UNIX, Novell, and MacOS ftp servers send their time */
+      /* Jul 06 12:57 or Jul  6  1999 */
+
+      if (strchr (str, ':') != NULL)
+        {
+          tmppos = strptime (str, "%h %d %H:%M", &curtime);
+          t = time (NULL);
+          loctime = localtime (&t);
+
+          if (curtime.tm_mon > loctime->tm_mon)
+            curtime.tm_year = loctime->tm_year - 1;
+          else
+            curtime.tm_year = loctime->tm_year;
+        }
+      else
+        tmppos = strptime (str, "%h %d %Y", &curtime);
+    }
+
+  if (tmppos != NULL)
+    ret = mktime (&curtime);
+  else
+    ret = 0;
+
+  if (endpos != NULL)
+    {
+      if (tmppos == NULL)
+        {
+          /* We cannot parse this date format. So, just skip this date field
+             and continue to the next token. This is mainly for the HTTP 
+             support */
+
+          *endpos = str;
+          for (num = 0; num < 2 && **endpos != '\0'; num++)
+            {
+              for (i=0; 
+                   (*endpos)[i] != ' ' && (*endpos)[i] != '\t' && 
+                    (*endpos)[i] != '\0'; 
+                   i++);
+              *endpos += i;
+
+              for (i=0; (*endpos)[i] == ' ' || (*endpos)[i] == '\t'; i++);
+              *endpos += i;
+            }
+        }
+      else
+        *endpos = tmppos;
+    }
+
+  return (ret);
+}
+
+
+static mode_t
+gftp_parse_vms_attribs (char **src, mode_t mask)
+{
+  char *endpos;
+  mode_t ret;
+
+  if (*src == NULL)
+    return (0);
+
+  if ((endpos = strchr (*src, ',')) != NULL)
+    *endpos = '\0';
+
+  ret = 0;
+  if (strchr (*src, 'R') != NULL)
+    ret |= S_IRUSR | S_IRGRP | S_IROTH;
+  if (strchr (*src, 'W') != NULL)
+    ret |= S_IWUSR | S_IWGRP | S_IWOTH;
+  if (strchr (*src, 'E') != NULL)
+    ret |= S_IXUSR | S_IXGRP | S_IXOTH;
+
+  *src = endpos + 1;
+
+  return (ret & mask);
+}
+
+
+static int
+gftp_parse_ls_vms (gftp_request * request, int fd, char *str, gftp_file * fle)
+{
+  char *curpos, *endpos, tempstr[1024];
+  int multiline;
+  ssize_t len;
+
+  /* .PINE-DEBUG1;1              9  21-AUG-2002 20:06 [MYERSRG] (RWED,RWED,,) */
+  /* WWW.DIR;1                   1  23-NOV-1999 05:47 [MYERSRG] (RWE,RWE,RE,E) */
+
+  /* Multiline VMS 
+  $MAIN.TPU$JOURNAL;1
+	1/18 8-JUN-2004 13:04:14  [NUCLEAR,FISSION]      (RWED,RWED,RE,)
+  TCPIP$FTP_SERVER.LOG;29
+	0/18 8-JUN-2004 14:42:04  [NUCLEAR,FISSION]      (RWED,RWED,RE,)
+  TCPIP$FTP_SERVER.LOG;28
+	5/18 8-JUN-2004 13:05:11  [NUCLEAR,FISSION]      (RWED,RWED,RE,)
+  TCPIP$FTP_SERVER.LOG;27
+	5/18 8-JUN-2004 13:03:51  [NUCLEAR,FISSION]      (RWED,RWED,RE,) */
+
+  if ((curpos = strchr (str, ';')) == NULL)
+    return (GFTP_EFATAL);
+
+  multiline = strchr (str, ' ') == NULL;
+
+  *curpos = '\0';
+  if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0)
+    {
+      fle->st_mode |= S_IFDIR;
+      *(curpos - 4) = '\0';
+    }
+
+  fle->file = g_strdup (str);
+
+  if (multiline)
+    {
+      if (request->get_next_dirlist_line == NULL)
+        return (GFTP_EFATAL);
+
+      len = request->get_next_dirlist_line (request, fd, tempstr,
+                                            sizeof (tempstr));
+      if (len <= 0)
+        return ((int) len);
+
+      for (curpos = tempstr; *curpos == ' ' || *curpos == '\t'; curpos++);
+    }
+  else
+    curpos = goto_next_token (curpos + 1);
+
+  fle->size = gftp_parse_file_size (curpos) * 512; /* Is this correct? */
+
+  curpos = goto_next_token (curpos);
+
+  fle->datetime = parse_vms_time (curpos, &curpos);
+
+  if (*curpos != '[')
+    return (GFTP_EFATAL);
+
+  if ((endpos = strchr (curpos, ']')) == NULL)
+    return (GFTP_EFATAL);
+
+  curpos = goto_next_token (endpos + 1);
+  if ((curpos = strchr (curpos, ',')) == NULL)
+    return (0);
+  curpos++;
+
+  fle->st_mode = gftp_parse_vms_attribs (&curpos, S_IRWXU);
+  fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXG);
+  fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXO);
+
+  fle->user = g_strdup ("");
+  fle->group = g_strdup ("");
+
+  return (0);
+}
+
+
+static int
+gftp_parse_ls_mvs (char *str, gftp_file * fle)
+{
+  char *curpos;
+
+  /* Volume Unit    Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname */
+  /* SVI52A 3390   2003/12/10  8  216  FB      80 27920  PS  CARDS.DELETES */
+  /* SVI528 3390   2003/12/12  1    5  FB      80 24000  PO  CLIST */
+
+  curpos = goto_next_token (str + 1);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  curpos = goto_next_token (curpos + 1);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  fle->datetime = parse_time (curpos, &curpos);
+
+  curpos = goto_next_token (curpos);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  curpos = goto_next_token (curpos + 1);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  fle->size = gftp_parse_file_size (curpos) * 55996; 
+  curpos = goto_next_token (curpos + 1);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  curpos = goto_next_token (curpos + 1);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  curpos = goto_next_token (curpos + 1);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  curpos = goto_next_token (curpos + 1);
+  if (curpos == NULL)
+    return (GFTP_EFATAL);
+
+  if (strncmp (curpos, "PS", 2) == 0)
+    fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+  else if (strncmp (curpos, "PO", 2) == 0)
+    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+  else
+    return (GFTP_EFATAL);
+
+  curpos = goto_next_token (curpos + 1);
+
+  fle->user = g_strdup (_("unknown"));
+  fle->group = g_strdup (_("unknown"));
+  fle->file = g_strdup (curpos);
+
+  return (0);
+}
+  
+
+static int
+gftp_parse_ls_eplf (char *str, gftp_file * fle)
+{
+  char *startpos;
+  int isdir = 0;
+
+  startpos = str;
+  while (startpos)
+    {
+      startpos++;
+      switch (*startpos)
+        {
+          case '/':
+            isdir = 1;
+            break;
+          case 's':
+            fle->size = gftp_parse_file_size (startpos + 1);
+            break;
+          case 'm':
+            fle->datetime = strtol (startpos + 1, NULL, 10);
+            break;
+        }
+      startpos = strchr (startpos, ',');
+    }
+
+  if ((startpos = strchr (str, 9)) == NULL)
+    return (GFTP_EFATAL);
+
+  if (isdir)
+    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+  else
+    fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+  fle->file = g_strdup (startpos + 1);
+  fle->user = g_strdup (_("unknown"));
+  fle->group = g_strdup (_("unknown"));
+  return (0);
+}
+
+
+static int
+gftp_parse_ls_unix (gftp_request * request, char *str, size_t slen,
+                    gftp_file * fle)
+{
+  char *endpos, *startpos, *pos, *attribs;
+  int cols;
+
+  /* If there is no space between the attribs and links field, just make one */
+  if (slen > 10)
+    str[10] = ' ';
+
+  /* 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++;
+    }
+
+  startpos = str;
+  /* Copy file attributes */
+  if ((startpos = copy_token (&attribs, startpos)) == NULL)
+    return (GFTP_EFATAL);
+
+  if (strlen (attribs) < 10)
+    return (GFTP_EFATAL);
+
+  fle->st_mode = gftp_convert_attributes_to_mode_t (attribs);
+  g_free (attribs);
+
+  if (cols >= 9)
+    {
+      /* Skip the number of links */
+      startpos = goto_next_token (startpos);
+
+      /* Copy the user that owns this file */
+      if ((startpos = copy_token (&fle->user, startpos)) == NULL)
+        return (GFTP_EFATAL);
+
+      /* Copy the group that owns this file */
+      if ((startpos = copy_token (&fle->group, startpos)) == NULL)
+        return (GFTP_EFATAL);
+    }
+  else
+    {
+      fle->group = g_strdup (_("unknown"));
+      if (cols == 8)
+        {
+          if ((startpos = copy_token (&fle->user, startpos)) == NULL)
+            return (GFTP_EFATAL);
+        }
+      else
+        fle->user = g_strdup (_("unknown"));
+      startpos = goto_next_token (startpos);
+    }
+
+  if (request->server_type == GFTP_DIRTYPE_CRAY)
+    {
+      /* See if this is a Cray directory listing. It has the following format:
+      drwx------     2 feiliu    g913     DK  common      4096 Sep 24  2001 wv */
+      if (cols == 11 && strstr (str, "->") == NULL)
+        {
+          startpos = goto_next_token (startpos);
+          startpos = goto_next_token (startpos);
+        }
+    }
+
+  /* See if this is a block or character device. We will store the major number
+     in the high word and the minor number in the low word.  */
+  if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode) &&
+      (endpos = strchr (startpos, ',')) != NULL)
+    {
+      fle->size = (unsigned long) strtol (startpos, NULL, 10) << 16;
+
+      startpos = endpos + 1;
+      while (*startpos == ' ')
+        startpos++;
+
+      /* Get the minor number */
+      if ((endpos = strchr (startpos, ' ')) == NULL)
+        return (GFTP_EFATAL);
+      fle->size |= strtol (startpos, NULL, 10) & 0xFF;
+    }
+  else
+    {
+      /* This is a regular file  */
+      if ((endpos = strchr (startpos, ' ')) == NULL)
+        return (GFTP_EFATAL);
+      fle->size = gftp_parse_file_size (startpos);
+    }
+
+  /* Skip the blanks till we get to the next entry */
+  startpos = endpos + 1;
+  while (*startpos == ' ')
+    startpos++;
+
+  fle->datetime = parse_time (startpos, &startpos);
+
+  /* Skip the blanks till we get to the next entry */
+  startpos = goto_next_token (startpos);
+
+  /* Parse the filename. If this file is a symbolic link, remove the -> part */
+  if (S_ISLNK (fle->st_mode) && ((endpos = strstr (startpos, "->")) != NULL))
+    *(endpos - 1) = '\0';
+
+  fle->file = g_strdup (startpos);
+
+  /* Uncomment this if you want to strip the spaces off of the end of the file.
+     I don't want to do this by default since there are valid filenames with
+     spaces at the end of them. Some broken FTP servers like the Paradyne IPC
+     DSLAMS append a bunch of spaces at the end of the file.
+  for (endpos = fle->file + strlen (fle->file) - 1; 
+       *endpos == ' '; 
+       *endpos-- = '\0');
+  */
+
+  return (0);
+}
+
+
+static int
+gftp_parse_ls_nt (char *str, gftp_file * fle)
+{
+  char *startpos;
+
+  startpos = str;
+  fle->datetime = parse_time (startpos, &startpos);
+
+  fle->user = g_strdup (_("unknown"));
+  fle->group = g_strdup (_("unknown"));
+
+  startpos = goto_next_token (startpos);
+
+  if (startpos[0] == '<')
+    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+  else
+    {
+      fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+      fle->size = gftp_parse_file_size (startpos);
+    }
+
+  startpos = goto_next_token (startpos);
+  fle->file = g_strdup (startpos);
+  return (0);
+}
+
+
+static int
+gftp_parse_ls_novell (char *str, gftp_file * fle)
+{
+  char *startpos;
+
+  if (str[12] != ' ')
+    return (GFTP_EFATAL);
+
+  str[12] = '\0';
+  fle->st_mode = gftp_convert_attributes_to_mode_t (str);
+  startpos = str + 13;
+
+  while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0')
+    startpos++;
+
+  if ((startpos = copy_token (&fle->user, startpos)) == NULL)
+    return (GFTP_EFATAL);
+
+  fle->group = g_strdup (_("unknown"));
+
+  while (*startpos != '\0' && !isdigit (*startpos))
+    startpos++;
+
+  fle->size = gftp_parse_file_size (startpos);
+
+  startpos = goto_next_token (startpos);
+  fle->datetime = parse_time (startpos, &startpos);
+
+  startpos = goto_next_token (startpos);
+  fle->file = g_strdup (startpos);
+  return (0);
+}
+
+
+int
+gftp_parse_ls (gftp_request * request, const char *lsoutput, gftp_file * fle,
+               int fd)
+{
+  char *str, *endpos, tmpchar;
+  int result, is_vms;
+  size_t len;
+
+  g_return_val_if_fail (lsoutput != NULL, GFTP_EFATAL);
+  g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
+
+  str = g_strdup (lsoutput);
+  memset (fle, 0, sizeof (*fle));
+
+  len = strlen (str);
+  if (len > 0 && str[len - 1] == '\n')
+    str[--len] = '\0';
+  if (len > 0 && str[len - 1] == '\r')
+    str[--len] = '\0';
+
+  switch (request->server_type)
+    {
+      case GFTP_DIRTYPE_CRAY:
+      case GFTP_DIRTYPE_UNIX:
+        result = gftp_parse_ls_unix (request, str, len, fle);
+        break;
+      case GFTP_DIRTYPE_EPLF:
+        result = gftp_parse_ls_eplf (str, fle);
+        break;
+      case GFTP_DIRTYPE_NOVELL:
+        result = gftp_parse_ls_novell (str, fle);
+        break;
+      case GFTP_DIRTYPE_DOS:
+        result = gftp_parse_ls_nt (str, fle);
+        break;
+      case GFTP_DIRTYPE_VMS:
+        result = gftp_parse_ls_vms (request, fd, str, fle);
+        break;
+      case GFTP_DIRTYPE_MVS:
+        result = gftp_parse_ls_mvs (str, fle);
+        break;
+      default: /* autodetect */
+        if (*lsoutput == '+')
+          result = gftp_parse_ls_eplf (str, fle);
+        else if (isdigit ((int) str[0]) && str[2] == '-')
+          result = gftp_parse_ls_nt (str, fle);
+        else if (str[1] == ' ' && str[2] == '[')
+          result = gftp_parse_ls_novell (str, fle);
+        else
+          {
+            if ((endpos = strchr (str, ' ')) != NULL)
+              {
+                /* If the first token in the string has a ; in it, then */
+                /* we'll assume that this is a VMS directory listing    */
+                tmpchar = *endpos;
+                *endpos = '\0';
+                is_vms = strchr (str, ';') != NULL;
+                *endpos = tmpchar;
+              }
+            else
+              is_vms = 0;
+
+            if (is_vms)
+              result = gftp_parse_ls_vms (request, fd, str, fle);
+            else
+              result = gftp_parse_ls_unix (request, str, len, fle);
+          }
+        break;
+    }
+  g_free (str);
+
+  return (result);
+}
+
--- a/lib/protocols.c	Tue Mar 04 12:02:47 2008 +0000
+++ b/lib/protocols.c	Tue Mar 04 12:28:40 2008 +0000
@@ -413,246 +413,6 @@
 }
 
 
-#if GLIB_MAJOR_VERSION > 1
-
-static /*@null@*/ char *
-_gftp_get_next_charset (char **curpos)
-{
-  char *ret, *endpos;
-  size_t len, retlen;
-
-  if (**curpos == '\0')
-    return (NULL);
-
-  for (; **curpos == ' ' || **curpos == '\t'; (*curpos)++);
-
-  if ((endpos = strchr (*curpos, ',')) == NULL)
-    len = strlen (*curpos) - 1; /* the trailing ',' should be omitted */
-  else
-    len = endpos - *curpos;
-
-  for (retlen = len - 1;
-       (*curpos)[retlen - 1] == ' ' || (*curpos)[retlen - 1] == '\t';
-       retlen--);
-
-  retlen++; /* Needed due to the len - 1 above... */
-  ret = g_malloc0 (retlen + 1);
-  memcpy (ret, *curpos, retlen);
-
-  for (*curpos += len; **curpos == ','; (*curpos)++);
-
-  return (ret);
-}
-
-
-static void
-_do_show_iconv_error (const char *str, char *charset, int from_utf8,
-                      GError * error)
-{
-  const char *fromset, *toset;
-
-  if (from_utf8)
-    {
-      fromset = "UTF-8";
-      toset = charset;
-    }
-  else
-    {
-      fromset = charset;
-      toset = "UTF-8";
-    }
-
-  printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
-          str, fromset, toset, error->message);
-}
-
-
-/*@null@*/ char *
-_do_convert_string (gftp_request * request, int is_filename, int force_local,
-                    const char *str, size_t *dest_len, int from_utf8)
-{
-  char *remote_charsets, *ret, *fromset, *toset, *stpos, *cur_charset;
-  GError * error;
-  gsize bread;
-
-  if (request == NULL)
-    return (NULL);
-
-  if (g_utf8_validate (str, -1, NULL) != from_utf8)
-    return (NULL);
-
-  error = NULL;
-  gftp_lookup_request_option (request, "remote_charsets", &remote_charsets);
-  if (*remote_charsets == '\0' || request->use_local_encoding ||
-      force_local == 1)
-    {
-      if (from_utf8)
-        {
-          if (is_filename)
-            ret = g_filename_from_utf8 (str, -1, &bread, dest_len, &error);
-          else
-            ret = g_locale_from_utf8 (str, -1, &bread, dest_len, &error);
-        }
-      else
-        {
-          if (is_filename)
-            ret = g_filename_to_utf8 (str, -1, &bread, dest_len, &error);
-          else
-            ret = g_locale_to_utf8 (str, -1, &bread, dest_len, &error);
-        }
-
-      if (ret == NULL)
-        _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
-
-      return (ret);
-    }
-
-  if (from_utf8)
-    {
-      if (request->iconv_from_initialized)
-        {
-          ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread, dest_len,
-                                      &error);
-          if (ret == NULL)
-            _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
-
-          return (ret);
-        }
-    }
-  else
-    {
-      if (request->iconv_to_initialized)
-        {
-          ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread, dest_len,
-                                      &error);
-          if (ret == NULL)
-            _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
-
-          return (ret);
-        }
-    }
-
-  stpos = remote_charsets;
-  while ((cur_charset = _gftp_get_next_charset (&stpos)) != NULL)
-    {
-      if (from_utf8)
-        {
-          fromset = "UTF-8";
-          toset = cur_charset;
-          if ((request->iconv_from = g_iconv_open (toset, fromset)) == (GIConv) -1)
-            {
-              g_free (cur_charset);
-              continue;
-            }
-
-          error = NULL;
-          if ((ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread,
-                                           dest_len, &error)) == NULL)
-            {
-              g_iconv_close (request->iconv_from);
-              request->iconv_from = NULL;
-              _do_show_iconv_error (str, cur_charset, from_utf8, error);
-              g_free (cur_charset);
-              continue;
-            }
-
-          request->iconv_from_initialized = 1;
-        }
-      else
-        {
-          fromset = cur_charset;
-          toset = "UTF-8";
-          if ((request->iconv_to = g_iconv_open (toset, fromset)) == (GIConv) -1)
-            {
-              g_free (cur_charset);
-              continue;
-            }
-
-          error = NULL;
-          if ((ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread,
-                                           dest_len, &error)) == NULL)
-            {
-              g_iconv_close (request->iconv_to);
-              request->iconv_to = NULL;
-              _do_show_iconv_error (str, cur_charset, from_utf8, error);
-              g_free (cur_charset);
-              continue;
-            }
-
-          request->iconv_to_initialized = 1;
-        }
-
-      request->iconv_charset = cur_charset;
-      return (ret);
-    }
-
-  return (NULL);
-}
-
-char *
-gftp_string_to_utf8 (gftp_request * request, const char *str, size_t *dest_len)
-{
-  return (_do_convert_string (request, 0, 0, str, dest_len, 0));
-}
-
-
-char *
-gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
-                       size_t *dest_len)
-{
-  return (_do_convert_string (request, 0, force_local, str, dest_len, 1));
-}
-
-
-char *
-gftp_filename_to_utf8 (gftp_request * request, const char *str,
-                       size_t *dest_len)
-{
-  return (_do_convert_string (request, 1, 0, str, dest_len, 0));
-}
-
-
-char *
-gftp_filename_from_utf8 (gftp_request * request, const char *str,
-                         size_t *dest_len)
-{
-  return (_do_convert_string (request, 1, 0, str, dest_len, 1));
-}
-
-#else
-
-char *
-gftp_string_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
-{
-  return (NULL);
-}
-
-
-char *
-gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
-                       size_t dest_len)
-{
-  return (NULL);
-}
-
-
-char *
-gftp_filename_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
-{
-  return (NULL);
-}
-
-
-char *
-gftp_filename_from_utf8 (gftp_request * request, int force_local,
-                         const char *str, size_t dest_len)
-{
-  return (NULL);
-}
-
-#endif
-
-
 int
 gftp_get_next_file (gftp_request * request, const char *filespec,
                     gftp_file * fle)
@@ -1157,746 +917,6 @@
 }
 
 
-/* FIXME - clean up this function */
-static int
-gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname, 
-                 unsigned int proxy_port)
-{
-  gftp_config_list_vars * proxy_hosts;
-  gftp_proxy_hosts * hostname;
-  size_t hostlen, domlen;
-  unsigned char addy[4];
-  struct sockaddr *addr;
-  GList * templist;
-  gint32 netaddr;
-  char *pos;
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-  struct addrinfo hints, *hostp;
-  unsigned int port;
-  int errnum;
-  char serv[8];
-#else
-  struct hostent host, *hostp;
-#endif
-
-  gftp_lookup_global_option ("dont_use_proxy", &proxy_hosts);
-
-  if (proxy_hostname == NULL || *proxy_hostname == '\0')
-    return (0);
-  else if (proxy_hosts->list == NULL)
-    return (proxy_hostname != NULL && 
-            *proxy_hostname != '\0');
-
-  hostp = NULL;
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-  memset (&hints, 0, sizeof (hints));
-  hints.ai_flags = AI_CANONNAME;
-  hints.ai_family = PF_UNSPEC;
-  hints.ai_socktype = SOCK_STREAM;
-
-  port = request->use_proxy ? proxy_port : request->port;
-  if (port == 0)
-    strcpy (serv, service);
-  else
-    snprintf (serv, sizeof (serv), "%d", port);
-
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), request->hostname);
-
-  if ((errnum = getaddrinfo (request->hostname, serv, &hints, 
-                             &hostp)) != 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 request->hostname, gai_strerror (errnum));
-      return (GFTP_ERETRYABLE);
-    }
-
-  addr = hostp->ai_addr;
-
-#else /* !HAVE_GETADDRINFO */
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), request->hostname);
-
-  if (!(hostp = r_gethostbyname (request->hostname, &host, NULL)))
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 request->hostname, g_strerror (errno));
-      return (GFTP_ERETRYABLE);
-    }
-
-  addr = (struct sockaddr *) host.h_addr_list[0];
-
-#endif /* HAVE_GETADDRINFO */
-
-  templist = proxy_hosts->list;
-  while (templist != NULL)
-    {
-      hostname = templist->data;
-      if (hostname->domain != NULL)
-        {
-           hostlen = strlen (request->hostname);
-           domlen = strlen (hostname->domain);
-           if (hostlen > domlen)
-             {
-                pos = request->hostname + hostlen - domlen;
-                if (strcmp (hostname->domain, pos) == 0)
-                  return (0);
-             }
-        }
-
-      if (hostname->ipv4_network_address != 0)
-        {
-          memcpy (addy, addr, sizeof (*addy));
-          netaddr =
-            (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) |
-             ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & 
-             hostname->ipv4_netmask;
-          if (netaddr == hostname->ipv4_network_address)
-            return (0);
-        }
-      templist = templist->next;
-    }
-
-  return (proxy_hostname != NULL && *proxy_hostname != '\0');
-}
-
-
-static char *
-copy_token (/*@out@*/ char **dest, char *source)
-{
-  /* This function is used internally by gftp_parse_ls () */
-  char *endpos, savepos;
-
-  endpos = source;
-  while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
-    endpos++;
-  if (*endpos == '\0')
-    {
-      *dest = NULL;
-      return (NULL);
-    }
-
-  savepos = *endpos;
-  *endpos = '\0';
-  *dest = g_malloc0 ((gulong) (endpos - source + 1));
-  strcpy (*dest, source);
-  *endpos = savepos;
-
-  /* Skip the blanks till we get to the next entry */
-  source = endpos + 1;
-  while ((*source == ' ' || *source == '\t') && *source != '\0')
-    source++;
-  return (source);
-}
-
-
-static char *
-goto_next_token (char *pos)
-{
-  while (*pos != ' ' && *pos != '\t' && *pos != '\0')
-    pos++;
-
-  while (*pos == ' ' || *pos == '\t')
-    pos++;
-
-  return (pos);
-}
-
-
-static time_t
-parse_vms_time (char *str, char **endpos)
-{
-  struct tm curtime;
-  time_t ret;
-
-  /* 8-JUN-2004 13:04:14 */
-  memset (&curtime, 0, sizeof (curtime));
-
-  *endpos = strptime (str, "%d-%b-%Y %H:%M:%S", &curtime);
-  if (*endpos == NULL)
-    *endpos = strptime (str, "%d-%b-%Y %H:%M", &curtime);
-  
-  if (*endpos != NULL)
-    {
-      ret = mktime (&curtime);
-      for (; **endpos == ' ' || **endpos == '\t'; (*endpos)++);
-    }
-  else
-    {
-      ret = 0;
-      *endpos = goto_next_token (str);
-      if (*endpos != NULL)
-        *endpos = goto_next_token (*endpos);
-    }
-
-  return (ret);
-}
-
-
-time_t
-parse_time (char *str, char **endpos)
-{
-  struct tm curtime, *loctime;
-  time_t t, ret;
-  char *tmppos;
-  size_t slen;
-  int i, num;
-
-  slen = strlen (str);
-  memset (&curtime, 0, sizeof (curtime));
-  curtime.tm_isdst = -1;
-
-  if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' && 
-      isdigit ((int) str[3]))
-    {
-      /* This is how DOS will return the date/time */
-      /* 07-06-99  12:57PM */
-
-      tmppos = strptime (str, "%m-%d-%y %I:%M%p", &curtime);
-    }
-  else if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' && 
-           isalpha (str[3]))
-    {
-      /* 10-Jan-2003 09:14 */
-      tmppos = strptime (str, "%d-%h-%Y %H:%M", &curtime);
-    }
-  else if (slen > 4 && isdigit ((int) str[0]) && str[4] == '/')
-    {
-      /* 2003/12/25 */
-      tmppos = strptime (str, "%Y/%m/%d", &curtime);
-    }
-  else
-    {
-      /* This is how most UNIX, Novell, and MacOS ftp servers send their time */
-      /* Jul 06 12:57 or Jul  6  1999 */
-
-      if (strchr (str, ':') != NULL)
-        {
-          tmppos = strptime (str, "%h %d %H:%M", &curtime);
-          t = time (NULL);
-          loctime = localtime (&t);
-
-          if (curtime.tm_mon > loctime->tm_mon)
-            curtime.tm_year = loctime->tm_year - 1;
-          else
-            curtime.tm_year = loctime->tm_year;
-        }
-      else
-        tmppos = strptime (str, "%h %d %Y", &curtime);
-    }
-
-  if (tmppos != NULL)
-    ret = mktime (&curtime);
-  else
-    ret = 0;
-
-  if (endpos != NULL)
-    {
-      if (tmppos == NULL)
-        {
-          /* We cannot parse this date format. So, just skip this date field
-             and continue to the next token. This is mainly for the HTTP 
-             support */
-
-          *endpos = str;
-          for (num = 0; num < 2 && **endpos != '\0'; num++)
-            {
-              for (i=0; 
-                   (*endpos)[i] != ' ' && (*endpos)[i] != '\t' && 
-                    (*endpos)[i] != '\0'; 
-                   i++);
-              *endpos += i;
-
-              for (i=0; (*endpos)[i] == ' ' || (*endpos)[i] == '\t'; i++);
-              *endpos += i;
-            }
-        }
-      else
-        *endpos = tmppos;
-    }
-
-  return (ret);
-}
-
-
-static mode_t
-gftp_parse_vms_attribs (char **src, mode_t mask)
-{
-  char *endpos;
-  mode_t ret;
-
-  if (*src == NULL)
-    return (0);
-
-  if ((endpos = strchr (*src, ',')) != NULL)
-    *endpos = '\0';
-
-  ret = 0;
-  if (strchr (*src, 'R') != NULL)
-    ret |= S_IRUSR | S_IRGRP | S_IROTH;
-  if (strchr (*src, 'W') != NULL)
-    ret |= S_IWUSR | S_IWGRP | S_IWOTH;
-  if (strchr (*src, 'E') != NULL)
-    ret |= S_IXUSR | S_IXGRP | S_IXOTH;
-
-  *src = endpos + 1;
-
-  return (ret & mask);
-}
-
-
-static int
-gftp_parse_ls_vms (gftp_request * request, int fd, char *str, gftp_file * fle)
-{
-  char *curpos, *endpos, tempstr[1024];
-  int multiline;
-  ssize_t len;
-
-  /* .PINE-DEBUG1;1              9  21-AUG-2002 20:06 [MYERSRG] (RWED,RWED,,) */
-  /* WWW.DIR;1                   1  23-NOV-1999 05:47 [MYERSRG] (RWE,RWE,RE,E) */
-
-  /* Multiline VMS 
-  $MAIN.TPU$JOURNAL;1
-	1/18 8-JUN-2004 13:04:14  [NUCLEAR,FISSION]      (RWED,RWED,RE,)
-  TCPIP$FTP_SERVER.LOG;29
-	0/18 8-JUN-2004 14:42:04  [NUCLEAR,FISSION]      (RWED,RWED,RE,)
-  TCPIP$FTP_SERVER.LOG;28
-	5/18 8-JUN-2004 13:05:11  [NUCLEAR,FISSION]      (RWED,RWED,RE,)
-  TCPIP$FTP_SERVER.LOG;27
-	5/18 8-JUN-2004 13:03:51  [NUCLEAR,FISSION]      (RWED,RWED,RE,) */
-
-  if ((curpos = strchr (str, ';')) == NULL)
-    return (GFTP_EFATAL);
-
-  multiline = strchr (str, ' ') == NULL;
-
-  *curpos = '\0';
-  if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0)
-    {
-      fle->st_mode |= S_IFDIR;
-      *(curpos - 4) = '\0';
-    }
-
-  fle->file = g_strdup (str);
-
-  if (multiline)
-    {
-      if (request->get_next_dirlist_line == NULL)
-        return (GFTP_EFATAL);
-
-      len = request->get_next_dirlist_line (request, fd, tempstr,
-                                            sizeof (tempstr));
-      if (len <= 0)
-        return ((int) len);
-
-      for (curpos = tempstr; *curpos == ' ' || *curpos == '\t'; curpos++);
-    }
-  else
-    curpos = goto_next_token (curpos + 1);
-
-  fle->size = gftp_parse_file_size (curpos) * 512; /* Is this correct? */
-
-  curpos = goto_next_token (curpos);
-
-  fle->datetime = parse_vms_time (curpos, &curpos);
-
-  if (*curpos != '[')
-    return (GFTP_EFATAL);
-
-  if ((endpos = strchr (curpos, ']')) == NULL)
-    return (GFTP_EFATAL);
-
-  curpos = goto_next_token (endpos + 1);
-  if ((curpos = strchr (curpos, ',')) == NULL)
-    return (0);
-  curpos++;
-
-  fle->st_mode = gftp_parse_vms_attribs (&curpos, S_IRWXU);
-  fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXG);
-  fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXO);
-
-  fle->user = g_strdup ("");
-  fle->group = g_strdup ("");
-
-  return (0);
-}
-
-
-static int
-gftp_parse_ls_mvs (char *str, gftp_file * fle)
-{
-  char *curpos;
-
-  /* Volume Unit    Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname */
-  /* SVI52A 3390   2003/12/10  8  216  FB      80 27920  PS  CARDS.DELETES */
-  /* SVI528 3390   2003/12/12  1    5  FB      80 24000  PO  CLIST */
-
-  curpos = goto_next_token (str + 1);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  curpos = goto_next_token (curpos + 1);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  fle->datetime = parse_time (curpos, &curpos);
-
-  curpos = goto_next_token (curpos);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  curpos = goto_next_token (curpos + 1);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  fle->size = gftp_parse_file_size (curpos) * 55996; 
-  curpos = goto_next_token (curpos + 1);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  curpos = goto_next_token (curpos + 1);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  curpos = goto_next_token (curpos + 1);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  curpos = goto_next_token (curpos + 1);
-  if (curpos == NULL)
-    return (GFTP_EFATAL);
-
-  if (strncmp (curpos, "PS", 2) == 0)
-    fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-  else if (strncmp (curpos, "PO", 2) == 0)
-    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
-  else
-    return (GFTP_EFATAL);
-
-  curpos = goto_next_token (curpos + 1);
-
-  fle->user = g_strdup (_("unknown"));
-  fle->group = g_strdup (_("unknown"));
-  fle->file = g_strdup (curpos);
-
-  return (0);
-}
-  
-
-static int
-gftp_parse_ls_eplf (char *str, gftp_file * fle)
-{
-  char *startpos;
-  int isdir = 0;
-
-  startpos = str;
-  while (startpos)
-    {
-      startpos++;
-      switch (*startpos)
-        {
-          case '/':
-            isdir = 1;
-            break;
-          case 's':
-            fle->size = gftp_parse_file_size (startpos + 1);
-            break;
-          case 'm':
-            fle->datetime = strtol (startpos + 1, NULL, 10);
-            break;
-        }
-      startpos = strchr (startpos, ',');
-    }
-
-  if ((startpos = strchr (str, 9)) == NULL)
-    return (GFTP_EFATAL);
-
-  if (isdir)
-    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
-  else
-    fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-
-  fle->file = g_strdup (startpos + 1);
-  fle->user = g_strdup (_("unknown"));
-  fle->group = g_strdup (_("unknown"));
-  return (0);
-}
-
-
-static int
-gftp_parse_ls_unix (gftp_request * request, char *str, size_t slen,
-                    gftp_file * fle)
-{
-  char *endpos, *startpos, *pos, *attribs;
-  int cols;
-
-  /* If there is no space between the attribs and links field, just make one */
-  if (slen > 10)
-    str[10] = ' ';
-
-  /* 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++;
-    }
-
-  startpos = str;
-  /* Copy file attributes */
-  if ((startpos = copy_token (&attribs, startpos)) == NULL)
-    return (GFTP_EFATAL);
-
-  if (strlen (attribs) < 10)
-    return (GFTP_EFATAL);
-
-  fle->st_mode = gftp_convert_attributes_to_mode_t (attribs);
-  g_free (attribs);
-
-  if (cols >= 9)
-    {
-      /* Skip the number of links */
-      startpos = goto_next_token (startpos);
-
-      /* Copy the user that owns this file */
-      if ((startpos = copy_token (&fle->user, startpos)) == NULL)
-        return (GFTP_EFATAL);
-
-      /* Copy the group that owns this file */
-      if ((startpos = copy_token (&fle->group, startpos)) == NULL)
-        return (GFTP_EFATAL);
-    }
-  else
-    {
-      fle->group = g_strdup (_("unknown"));
-      if (cols == 8)
-        {
-          if ((startpos = copy_token (&fle->user, startpos)) == NULL)
-            return (GFTP_EFATAL);
-        }
-      else
-        fle->user = g_strdup (_("unknown"));
-      startpos = goto_next_token (startpos);
-    }
-
-  if (request->server_type == GFTP_DIRTYPE_CRAY)
-    {
-      /* See if this is a Cray directory listing. It has the following format:
-      drwx------     2 feiliu    g913     DK  common      4096 Sep 24  2001 wv */
-      if (cols == 11 && strstr (str, "->") == NULL)
-        {
-          startpos = goto_next_token (startpos);
-          startpos = goto_next_token (startpos);
-        }
-    }
-
-  /* See if this is a block or character device. We will store the major number
-     in the high word and the minor number in the low word.  */
-  if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode) &&
-      (endpos = strchr (startpos, ',')) != NULL)
-    {
-      fle->size = (unsigned long) strtol (startpos, NULL, 10) << 16;
-
-      startpos = endpos + 1;
-      while (*startpos == ' ')
-        startpos++;
-
-      /* Get the minor number */
-      if ((endpos = strchr (startpos, ' ')) == NULL)
-        return (GFTP_EFATAL);
-      fle->size |= strtol (startpos, NULL, 10) & 0xFF;
-    }
-  else
-    {
-      /* This is a regular file  */
-      if ((endpos = strchr (startpos, ' ')) == NULL)
-        return (GFTP_EFATAL);
-      fle->size = gftp_parse_file_size (startpos);
-    }
-
-  /* Skip the blanks till we get to the next entry */
-  startpos = endpos + 1;
-  while (*startpos == ' ')
-    startpos++;
-
-  fle->datetime = parse_time (startpos, &startpos);
-
-  /* Skip the blanks till we get to the next entry */
-  startpos = goto_next_token (startpos);
-
-  /* Parse the filename. If this file is a symbolic link, remove the -> part */
-  if (S_ISLNK (fle->st_mode) && ((endpos = strstr (startpos, "->")) != NULL))
-    *(endpos - 1) = '\0';
-
-  fle->file = g_strdup (startpos);
-
-  /* Uncomment this if you want to strip the spaces off of the end of the file.
-     I don't want to do this by default since there are valid filenames with
-     spaces at the end of them. Some broken FTP servers like the Paradyne IPC
-     DSLAMS append a bunch of spaces at the end of the file.
-  for (endpos = fle->file + strlen (fle->file) - 1; 
-       *endpos == ' '; 
-       *endpos-- = '\0');
-  */
-
-  return (0);
-}
-
-
-static int
-gftp_parse_ls_nt (char *str, gftp_file * fle)
-{
-  char *startpos;
-
-  startpos = str;
-  fle->datetime = parse_time (startpos, &startpos);
-
-  fle->user = g_strdup (_("unknown"));
-  fle->group = g_strdup (_("unknown"));
-
-  startpos = goto_next_token (startpos);
-
-  if (startpos[0] == '<')
-    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
-  else
-    {
-      fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-      fle->size = gftp_parse_file_size (startpos);
-    }
-
-  startpos = goto_next_token (startpos);
-  fle->file = g_strdup (startpos);
-  return (0);
-}
-
-
-static int
-gftp_parse_ls_novell (char *str, gftp_file * fle)
-{
-  char *startpos;
-
-  if (str[12] != ' ')
-    return (GFTP_EFATAL);
-
-  str[12] = '\0';
-  fle->st_mode = gftp_convert_attributes_to_mode_t (str);
-  startpos = str + 13;
-
-  while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0')
-    startpos++;
-
-  if ((startpos = copy_token (&fle->user, startpos)) == NULL)
-    return (GFTP_EFATAL);
-
-  fle->group = g_strdup (_("unknown"));
-
-  while (*startpos != '\0' && !isdigit (*startpos))
-    startpos++;
-
-  fle->size = gftp_parse_file_size (startpos);
-
-  startpos = goto_next_token (startpos);
-  fle->datetime = parse_time (startpos, &startpos);
-
-  startpos = goto_next_token (startpos);
-  fle->file = g_strdup (startpos);
-  return (0);
-}
-
-
-int
-gftp_parse_ls (gftp_request * request, const char *lsoutput, gftp_file * fle,
-               int fd)
-{
-  char *str, *endpos, tmpchar;
-  int result, is_vms;
-  size_t len;
-
-  g_return_val_if_fail (lsoutput != NULL, GFTP_EFATAL);
-  g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
-
-  str = g_strdup (lsoutput);
-  memset (fle, 0, sizeof (*fle));
-
-  len = strlen (str);
-  if (len > 0 && str[len - 1] == '\n')
-    str[--len] = '\0';
-  if (len > 0 && str[len - 1] == '\r')
-    str[--len] = '\0';
-
-  switch (request->server_type)
-    {
-      case GFTP_DIRTYPE_CRAY:
-      case GFTP_DIRTYPE_UNIX:
-        result = gftp_parse_ls_unix (request, str, len, fle);
-        break;
-      case GFTP_DIRTYPE_EPLF:
-        result = gftp_parse_ls_eplf (str, fle);
-        break;
-      case GFTP_DIRTYPE_NOVELL:
-        result = gftp_parse_ls_novell (str, fle);
-        break;
-      case GFTP_DIRTYPE_DOS:
-        result = gftp_parse_ls_nt (str, fle);
-        break;
-      case GFTP_DIRTYPE_VMS:
-        result = gftp_parse_ls_vms (request, fd, str, fle);
-        break;
-      case GFTP_DIRTYPE_MVS:
-        result = gftp_parse_ls_mvs (str, fle);
-        break;
-      default: /* autodetect */
-        if (*lsoutput == '+')
-          result = gftp_parse_ls_eplf (str, fle);
-        else if (isdigit ((int) str[0]) && str[2] == '-')
-          result = gftp_parse_ls_nt (str, fle);
-        else if (str[1] == ' ' && str[2] == '[')
-          result = gftp_parse_ls_novell (str, fle);
-        else
-          {
-            if ((endpos = strchr (str, ' ')) != NULL)
-              {
-                /* If the first token in the string has a ; in it, then */
-                /* we'll assume that this is a VMS directory listing    */
-                tmpchar = *endpos;
-                *endpos = '\0';
-                is_vms = strchr (str, ';') != NULL;
-                *endpos = tmpchar;
-              }
-            else
-              is_vms = 0;
-
-            if (is_vms)
-              result = gftp_parse_ls_vms (request, fd, str, fle);
-            else
-              result = gftp_parse_ls_unix (request, str, len, fle);
-          }
-        break;
-    }
-  g_free (str);
-
-  return (result);
-}
-
-
 static GHashTable *
 gftp_gen_dir_hash (gftp_request * request, int *ret)
 {
@@ -2322,280 +1342,6 @@
 }
 
 
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-static int
-get_port (struct addrinfo *addr)
-{
-  struct sockaddr_in * saddr;
-  int port;
-
-  if (addr->ai_family == AF_INET)
-    {
-      saddr = (struct sockaddr_in *) addr->ai_addr;
-      port = ntohs (saddr->sin_port);
-    }
-  else
-    port = 0;
-
-  return (port);
-}
-
-
-int
-gftp_connect_server_with_getaddr (gftp_request * request, char *service,
-                                  char *proxy_hostname, unsigned int proxy_port)
-{
-  struct addrinfo *hostp, *current_hostp;
-  char *connect_host, *disphost;
-  struct addrinfo hints, *res;
-  intptr_t enable_ipv6;
-  unsigned int port;
-  int ret, sock = -1;
-  char serv[8];
-
-  if ((ret = gftp_need_proxy (request, service, proxy_hostname,
-                                 proxy_port)) < 0)
-    return (ret);
-  else
-    request->use_proxy = ret;
-
-  gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6);
-
-  memset (&hints, 0, sizeof (hints));
-  hints.ai_flags = AI_CANONNAME;
-
-  hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET;
-  hints.ai_socktype = SOCK_STREAM;
-
-  if (request->use_proxy)
-    {
-      connect_host = proxy_hostname;
-      port = proxy_port;
-    }
-  else
-    {
-      connect_host = request->hostname;
-      port = request->port;
-    }
-
-  if (port == 0)
-    strcpy (serv, service); 
-  else
-    snprintf (serv, sizeof (serv), "%d", port);
-
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), connect_host);
-  if ((ret = getaddrinfo (connect_host, serv, &hints, 
-                             &hostp)) != 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 connect_host, gai_strerror (ret));
-      return (GFTP_ERETRYABLE);
-    }
-
-  disphost = connect_host;
-  for (res = hostp; res != NULL; res = res->ai_next)
-    {
-      disphost = res->ai_canonname ? res->ai_canonname : connect_host;
-      port = get_port (res);
-      if (!request->use_proxy)
-        request->port = port;
-
-      if ((sock = socket (res->ai_family, res->ai_socktype, 
-                          res->ai_protocol)) < 0)
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Failed to create a socket: %s\n"),
-                                     g_strerror (errno));
-          continue; 
-        } 
-
-      request->logging_function (gftp_logging_misc, request,
-                                 _("Trying %s:%d\n"), disphost, port);
-
-      if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Cannot connect to %s: %s\n"),
-                                     disphost, g_strerror (errno));
-          close (sock);
-          continue;
-        }
-
-      current_hostp = res;
-      request->ai_family = res->ai_family;
-      break;
-    }
-
-  if (res == NULL)
-    {
-      if (hostp != NULL)
-        freeaddrinfo (hostp);
-      
-      return (GFTP_ERETRYABLE);
-    }
-
-  request->remote_addr_len = current_hostp->ai_addrlen;
-  request->remote_addr = g_malloc0 (request->remote_addr_len);
-  memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr,
-          request->remote_addr_len);
-
-  request->logging_function (gftp_logging_misc, request,
-                             _("Connected to %s:%d\n"), connect_host, port);
-
-  return (sock);
-}
-#endif
-
-
-int
-gftp_connect_server_legacy (gftp_request * request, char *service,
-                            char *proxy_hostname, unsigned int proxy_port)
-{
-  struct sockaddr_in remote_address;
-  char *connect_host, *disphost;
-  struct hostent host, *hostp;
-  struct servent serv_struct;
-  int ret, sock, curhost;
-  unsigned int port;
-
-  if ((ret = gftp_need_proxy (request, service, proxy_hostname,
-                              proxy_port)) < 0)
-    return (ret);
-
-  request->use_proxy = ret;
-  if (request->use_proxy == 1)
-    hostp = NULL;
-
-  request->ai_family = AF_INET;
-  if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Failed to create a IPv4 socket: %s\n"),
-                                 g_strerror (errno));
-      return (GFTP_ERETRYABLE);
-    }
-
-  memset (&remote_address, 0, sizeof (remote_address));
-  remote_address.sin_family = AF_INET;
-
-  if (request->use_proxy)
-    {
-      connect_host = proxy_hostname;
-      port = proxy_port;
-    }
-  else
-    {
-      connect_host = request->hostname;
-      port = request->port;
-    }
-
-  if (port == 0)
-    {
-      if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Cannot look up service name %s/tcp. Please check your services file\n"),
-                                     service);
-          close (sock);
-          return (GFTP_EFATAL);
-        }
-
-      port = ntohs (serv_struct.s_port);
-
-      if (!request->use_proxy)
-        request->port = port;
-    }
-
-  remote_address.sin_port = htons (port);
-
-  request->logging_function (gftp_logging_misc, request,
-                             _("Looking up %s\n"), connect_host);
-
-  if (!(hostp = r_gethostbyname (connect_host, &host, NULL)))
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot look up hostname %s: %s\n"),
-                                 connect_host, g_strerror (errno));
-      close (sock);
-      return (GFTP_ERETRYABLE);
-    }
-
-  disphost = NULL;
-  for (curhost = 0;
-       host.h_addr_list[curhost] != NULL;
-       curhost++)
-    {
-      disphost = host.h_name;
-      memcpy (&remote_address.sin_addr,
-              host.h_addr_list[curhost],
-              host.h_length);
-      request->logging_function (gftp_logging_misc, request,
-                                 _("Trying %s:%d\n"),
-                                 host.h_name, port);
-
-      if (connect (sock, (struct sockaddr *) &remote_address,
-                   sizeof (remote_address)) == -1)
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Cannot connect to %s: %s\n"),
-                                     connect_host, g_strerror (errno));
-        }
-      break;
-    }
-
-  if (host.h_addr_list[curhost] == NULL)
-    {
-      close (sock);
-      return (GFTP_ERETRYABLE);
-    }
-
-  return (sock);
-}
-
-
-int
-gftp_connect_server (gftp_request * request, char *service,
-                     char *proxy_hostname, unsigned int proxy_port)
-{
-  int sock;
-
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-  sock = gftp_connect_server_with_getaddr (request, service, proxy_hostname,
-                                           proxy_port);
-#else
-  sock = gftp_connect_server_legacy (request, service, proxy_hostname,
-                                     proxy_port);
-#endif
-
-  if (sock < 0)
-    return (sock);
-
-  if (fcntl (sock, F_SETFD, 1) == -1)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Error: Cannot set close on exec flag: %s\n"),
-                                 g_strerror (errno));
-      close (sock);
-      return (GFTP_ERETRYABLE);
-    }
-
-  if (gftp_fd_set_sockblocking (request, sock, 1) < 0)
-    {
-      close (sock);
-      return (GFTP_ERETRYABLE);
-    }
-
-  request->datafd = sock;
-
-  if (request->post_connect != NULL)
-    return (request->post_connect (request));
-
-  return (0);
-}
-
-
 int
 gftp_set_config_options (gftp_request * request)
 {
@@ -2649,345 +1395,6 @@
 
 
 void
-gftp_free_getline_buffer (gftp_getline_buffer ** rbuf)
-{
-  g_free ((*rbuf)->buffer);
-  g_free (*rbuf);
-  *rbuf = NULL;
-}
-
-
-ssize_t
-gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, 
-               char * str, size_t len, int fd)
-{
-  ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size,
-                            int fd);
-  char *pos, *nextpos;
-  size_t rlen, nslen;
-  int end_of_buffer;
-  ssize_t ret;
-
-  if (request == NULL || request->read_function == NULL)
-    read_function = gftp_fd_read;
-  else
-    read_function = request->read_function;
-
-  if (*rbuf == NULL)
-    {
-      *rbuf = g_malloc0 (sizeof (**rbuf));
-      (*rbuf)->max_bufsize = len;
-      (*rbuf)->buffer = g_malloc0 ((gulong) ((*rbuf)->max_bufsize + 1));
-
-      if ((ret = read_function (request, (*rbuf)->buffer, 
-                                (*rbuf)->max_bufsize, fd)) <= 0)
-        {
-          gftp_free_getline_buffer (rbuf);
-          return (ret);
-        }
-      (*rbuf)->buffer[ret] = '\0';
-      (*rbuf)->cur_bufsize = ret;
-      (*rbuf)->curpos = (*rbuf)->buffer;
-    }
-
-  ret = 0;
-  while (1)
-    {
-      pos = strchr ((*rbuf)->curpos, '\n');
-      end_of_buffer = (*rbuf)->curpos == (*rbuf)->buffer && 
-            ((*rbuf)->max_bufsize == (*rbuf)->cur_bufsize || (*rbuf)->eof);
-
-      if ((*rbuf)->cur_bufsize > 0 && (pos != NULL || end_of_buffer))
-        {
-          if (pos != NULL)
-            {
-              nslen = pos - (*rbuf)->curpos + 1;
-              nextpos = pos + 1;
-              if (pos > (*rbuf)->curpos && *(pos - 1) == '\r')
-                pos--;
-              *pos = '\0';
-            }
-          else
-            {
-              nslen = (*rbuf)->cur_bufsize;
-              nextpos = NULL;
-
-              /* This is not an overflow since we allocated one extra byte to
-                 buffer above */
-              ((*rbuf)->buffer)[nslen] = '\0';
-            }
-
-          strncpy (str, (*rbuf)->curpos, len);
-          str[len - 1] = '\0';
-          (*rbuf)->cur_bufsize -= nslen;
-
-          if (nextpos != NULL)
-            (*rbuf)->curpos = nextpos;
-          else
-            (*rbuf)->cur_bufsize = 0;
-
-          ret = nslen;
-          break;
-        }
-      else
-        {
-          if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0')
-            {
-              rlen = (*rbuf)->max_bufsize;
-              pos = (*rbuf)->buffer;
-            }
-          else
-            {
-              memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize);
-              pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize;
-              rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize;
-            }
-
-          (*rbuf)->curpos = (*rbuf)->buffer;
-
-          if ((*rbuf)->eof)
-            ret = 0;
-          else
-            {
-              ret = read_function (request, pos, rlen, fd);
-              if (ret < 0)
-                {
-                  gftp_free_getline_buffer (rbuf);
-                  return (ret);
-                }
-            }
-
-          if (ret == 0)
-            {
-              if ((*rbuf)->cur_bufsize == 0)
-                {
-                  gftp_free_getline_buffer (rbuf);
-                  return (ret);
-                }
-
-              (*rbuf)->eof = 1;
-            }
-
-          (*rbuf)->cur_bufsize += ret;
-          (*rbuf)->buffer[(*rbuf)->cur_bufsize] = '\0';
-        }
-    }
-
-  return (ret);
-}
-
-
-ssize_t 
-gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd)
-{
-  intptr_t network_timeout;
-  struct timeval tv;
-  fd_set fset;
-  ssize_t ret;
-  int s_ret;
-
-  g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
-
-  gftp_lookup_request_option (request, "network_timeout", &network_timeout);  
-
-  errno = 0;
-  ret = 0;
-  FD_ZERO (&fset);
-
-  do
-    {
-      FD_SET (fd, &fset);
-      tv.tv_sec = network_timeout;
-      tv.tv_usec = 0;
-      s_ret = select (fd + 1, &fset, NULL, NULL, &tv);
-      if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
-        {
-          if (request != NULL && request->cancel)
-            {
-              gftp_disconnect (request);
-              return (GFTP_ERETRYABLE);
-            }
-
-          continue;
-        }
-      else if (s_ret <= 0)
-        {
-          if (request != NULL)
-            {
-              request->logging_function (gftp_logging_error, request,
-                                         _("Connection to %s timed out\n"),
-                                         request->hostname);
-              gftp_disconnect (request);
-            }
-
-          return (GFTP_ERETRYABLE);
-        }
-
-      if ((ret = read (fd, ptr, size)) < 0)
-        {
-          if (errno == EINTR || errno == EAGAIN)
-            {
-              if (request != NULL && request->cancel)
-                {
-                  gftp_disconnect (request);
-                  return (GFTP_ERETRYABLE);
-                }
-
-              continue;
-            }
- 
-          if (request != NULL)
-            {
-              request->logging_function (gftp_logging_error, request,
-                                   _("Error: Could not read from socket: %s\n"),
-                                    g_strerror (errno));
-              gftp_disconnect (request);
-            }
-
-          return (GFTP_ERETRYABLE);
-        }
-
-      break;
-    }
-  while (1);
-
-  return (ret);
-}
-
-
-ssize_t 
-gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd)
-{
-  intptr_t network_timeout;
-  struct timeval tv;
-  int ret, s_ret;
-  ssize_t w_ret;
-  fd_set fset;
-
-  g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
-
-  gftp_lookup_request_option (request, "network_timeout", &network_timeout);  
-
-  errno = 0;
-  ret = 0;
-  FD_ZERO (&fset);
-
-  do
-    {
-      FD_SET (fd, &fset);
-      tv.tv_sec = network_timeout;
-      tv.tv_usec = 0;
-      s_ret = select (fd + 1, NULL, &fset, NULL, &tv);
-      if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
-        {
-          if (request != NULL && request->cancel)
-            {
-              gftp_disconnect (request);
-              return (GFTP_ERETRYABLE);
-            }
-
-          continue;
-        }
-      else if (s_ret <= 0)
-        {
-          if (request != NULL)
-            {
-              request->logging_function (gftp_logging_error, request,
-                                         _("Connection to %s timed out\n"),
-                                         request->hostname);
-              gftp_disconnect (request);
-            }
-
-          return (GFTP_ERETRYABLE);
-        }
-
-      w_ret = write (fd, ptr, size);
-      if (w_ret < 0)
-        {
-          if (errno == EINTR || errno == EAGAIN)
-            {
-              if (request != NULL && request->cancel)
-                {
-                  gftp_disconnect (request);
-                  return (GFTP_ERETRYABLE);
-                }
-
-              continue;
-             }
- 
-          if (request != NULL)
-            {
-              request->logging_function (gftp_logging_error, request,
-                                    _("Error: Could not write to socket: %s\n"),
-                                    g_strerror (errno));
-              gftp_disconnect (request);
-            }
-
-          return (GFTP_ERETRYABLE);
-        }
-
-      ptr += w_ret;
-      size -= w_ret;
-      ret += w_ret;
-    }
-  while (size > 0);
-
-  return (ret);
-}
-
-
-ssize_t 
-gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...)
-{
-  char *tempstr;
-  va_list argp;
-  ssize_t ret;
-
-  va_start (argp, fmt);
-  tempstr = g_strdup_vprintf (fmt, argp);
-  va_end (argp);
-
-  ret = request->write_function (request, tempstr, strlen (tempstr), fd);
-  g_free (tempstr);
-  return (ret);
-}
-
-
-int
-gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking)
-{
-  int flags;
-
-  g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
-
-  if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot get socket flags: %s\n"),
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (GFTP_ERETRYABLE);
-    }
-
-  if (non_blocking)
-    flags |= O_NONBLOCK;
-  else
-    flags &= ~O_NONBLOCK;
-
-  if (fcntl (fd, F_SETFL, flags) < 0)
-    {
-      request->logging_function (gftp_logging_error, request,
-                                 _("Cannot set socket to non-blocking: %s\n"),
-                                 g_strerror (errno));
-      gftp_disconnect (request);
-      return (GFTP_ERETRYABLE);
-    }
-
-  return (0);
-}
-
-
-void
 gftp_swap_socks (gftp_request * dest, gftp_request * source)
 {
   g_return_if_fail (dest != NULL);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/socket-connect.c	Tue Mar 04 12:28:40 2008 +0000
@@ -0,0 +1,401 @@
+/*****************************************************************************/
+/*  socket-connect.c - contains functions for connecting to a server         */
+/*  Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org>                  */
+/*                                                                           */
+/*  This program is free software; you can redistribute it and/or modify     */
+/*  it under the terms of the GNU General Public License as published by     */
+/*  the Free Software Foundation; either version 2 of the License, or        */
+/*  (at your option) any later version.                                      */
+/*                                                                           */
+/*  This program is distributed in the hope that it will be useful,          */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/*  GNU General Public License for more details.                             */
+/*                                                                           */
+/*  You should have received a copy of the GNU General Public License        */
+/*  along with this program; if not, write to the Free Software              */
+/*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+/* FIXME - clean up this function */
+static int
+gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname, 
+                 unsigned int proxy_port)
+{
+  gftp_config_list_vars * proxy_hosts;
+  gftp_proxy_hosts * hostname;
+  size_t hostlen, domlen;
+  unsigned char addy[4];
+  struct sockaddr *addr;
+  GList * templist;
+  gint32 netaddr;
+  char *pos;
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+  struct addrinfo hints, *hostp;
+  unsigned int port;
+  int errnum;
+  char serv[8];
+#else
+  struct hostent host, *hostp;
+#endif
+
+  gftp_lookup_global_option ("dont_use_proxy", &proxy_hosts);
+
+  if (proxy_hostname == NULL || *proxy_hostname == '\0')
+    return (0);
+  else if (proxy_hosts->list == NULL)
+    return (proxy_hostname != NULL && 
+            *proxy_hostname != '\0');
+
+  hostp = NULL;
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_flags = AI_CANONNAME;
+  hints.ai_family = PF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+
+  port = request->use_proxy ? proxy_port : request->port;
+  if (port == 0)
+    strcpy (serv, service);
+  else
+    snprintf (serv, sizeof (serv), "%d", port);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Looking up %s\n"), request->hostname);
+
+  if ((errnum = getaddrinfo (request->hostname, serv, &hints, 
+                             &hostp)) != 0)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot look up hostname %s: %s\n"),
+                                 request->hostname, gai_strerror (errnum));
+      return (GFTP_ERETRYABLE);
+    }
+
+  addr = hostp->ai_addr;
+
+#else /* !HAVE_GETADDRINFO */
+  request->logging_function (gftp_logging_misc, request,
+                             _("Looking up %s\n"), request->hostname);
+
+  if (!(hostp = r_gethostbyname (request->hostname, &host, NULL)))
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot look up hostname %s: %s\n"),
+                                 request->hostname, g_strerror (errno));
+      return (GFTP_ERETRYABLE);
+    }
+
+  addr = (struct sockaddr *) host.h_addr_list[0];
+
+#endif /* HAVE_GETADDRINFO */
+
+  templist = proxy_hosts->list;
+  while (templist != NULL)
+    {
+      hostname = templist->data;
+      if (hostname->domain != NULL)
+        {
+           hostlen = strlen (request->hostname);
+           domlen = strlen (hostname->domain);
+           if (hostlen > domlen)
+             {
+                pos = request->hostname + hostlen - domlen;
+                if (strcmp (hostname->domain, pos) == 0)
+                  return (0);
+             }
+        }
+
+      if (hostname->ipv4_network_address != 0)
+        {
+          memcpy (addy, addr, sizeof (*addy));
+          netaddr =
+            (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) |
+             ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & 
+             hostname->ipv4_netmask;
+          if (netaddr == hostname->ipv4_network_address)
+            return (0);
+        }
+      templist = templist->next;
+    }
+
+  return (proxy_hostname != NULL && *proxy_hostname != '\0');
+}
+
+
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+static int
+get_port (struct addrinfo *addr)
+{
+  struct sockaddr_in * saddr;
+  int port;
+
+  if (addr->ai_family == AF_INET)
+    {
+      saddr = (struct sockaddr_in *) addr->ai_addr;
+      port = ntohs (saddr->sin_port);
+    }
+  else
+    port = 0;
+
+  return (port);
+}
+
+
+static int
+gftp_connect_server_with_getaddr (gftp_request * request, char *service,
+                                  char *proxy_hostname, unsigned int proxy_port)
+{
+  struct addrinfo *hostp, *current_hostp;
+  char *connect_host, *disphost;
+  struct addrinfo hints, *res;
+  intptr_t enable_ipv6;
+  unsigned int port;
+  int ret, sock = -1;
+  char serv[8];
+
+  if ((ret = gftp_need_proxy (request, service, proxy_hostname,
+                                 proxy_port)) < 0)
+    return (ret);
+  else
+    request->use_proxy = ret;
+
+  gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6);
+
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_flags = AI_CANONNAME;
+
+  hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+
+  if (request->use_proxy)
+    {
+      connect_host = proxy_hostname;
+      port = proxy_port;
+    }
+  else
+    {
+      connect_host = request->hostname;
+      port = request->port;
+    }
+
+  if (port == 0)
+    strcpy (serv, service); 
+  else
+    snprintf (serv, sizeof (serv), "%d", port);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Looking up %s\n"), connect_host);
+  if ((ret = getaddrinfo (connect_host, serv, &hints, 
+                             &hostp)) != 0)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot look up hostname %s: %s\n"),
+                                 connect_host, gai_strerror (ret));
+      return (GFTP_ERETRYABLE);
+    }
+
+  disphost = connect_host;
+  for (res = hostp; res != NULL; res = res->ai_next)
+    {
+      disphost = res->ai_canonname ? res->ai_canonname : connect_host;
+      port = get_port (res);
+      if (!request->use_proxy)
+        request->port = port;
+
+      if ((sock = socket (res->ai_family, res->ai_socktype, 
+                          res->ai_protocol)) < 0)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Failed to create a socket: %s\n"),
+                                     g_strerror (errno));
+          continue; 
+        } 
+
+      request->logging_function (gftp_logging_misc, request,
+                                 _("Trying %s:%d\n"), disphost, port);
+
+      if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Cannot connect to %s: %s\n"),
+                                     disphost, g_strerror (errno));
+          close (sock);
+          continue;
+        }
+
+      current_hostp = res;
+      request->ai_family = res->ai_family;
+      break;
+    }
+
+  if (res == NULL)
+    {
+      if (hostp != NULL)
+        freeaddrinfo (hostp);
+      
+      return (GFTP_ERETRYABLE);
+    }
+
+  request->remote_addr_len = current_hostp->ai_addrlen;
+  request->remote_addr = g_malloc0 (request->remote_addr_len);
+  memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr,
+          request->remote_addr_len);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Connected to %s:%d\n"), connect_host, port);
+
+  return (sock);
+}
+#endif
+
+
+static int
+gftp_connect_server_legacy (gftp_request * request, char *service,
+                            char *proxy_hostname, unsigned int proxy_port)
+{
+  struct sockaddr_in remote_address;
+  char *connect_host, *disphost;
+  struct hostent host, *hostp;
+  struct servent serv_struct;
+  int ret, sock, curhost;
+  unsigned int port;
+
+  if ((ret = gftp_need_proxy (request, service, proxy_hostname,
+                              proxy_port)) < 0)
+    return (ret);
+
+  request->use_proxy = ret;
+  if (request->use_proxy == 1)
+    hostp = NULL;
+
+  request->ai_family = AF_INET;
+  if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Failed to create a IPv4 socket: %s\n"),
+                                 g_strerror (errno));
+      return (GFTP_ERETRYABLE);
+    }
+
+  memset (&remote_address, 0, sizeof (remote_address));
+  remote_address.sin_family = AF_INET;
+
+  if (request->use_proxy)
+    {
+      connect_host = proxy_hostname;
+      port = proxy_port;
+    }
+  else
+    {
+      connect_host = request->hostname;
+      port = request->port;
+    }
+
+  if (port == 0)
+    {
+      if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Cannot look up service name %s/tcp. Please check your services file\n"),
+                                     service);
+          close (sock);
+          return (GFTP_EFATAL);
+        }
+
+      port = ntohs (serv_struct.s_port);
+
+      if (!request->use_proxy)
+        request->port = port;
+    }
+
+  remote_address.sin_port = htons (port);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Looking up %s\n"), connect_host);
+
+  if (!(hostp = r_gethostbyname (connect_host, &host, NULL)))
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot look up hostname %s: %s\n"),
+                                 connect_host, g_strerror (errno));
+      close (sock);
+      return (GFTP_ERETRYABLE);
+    }
+
+  disphost = NULL;
+  for (curhost = 0;
+       host.h_addr_list[curhost] != NULL;
+       curhost++)
+    {
+      disphost = host.h_name;
+      memcpy (&remote_address.sin_addr,
+              host.h_addr_list[curhost],
+              host.h_length);
+      request->logging_function (gftp_logging_misc, request,
+                                 _("Trying %s:%d\n"),
+                                 host.h_name, port);
+
+      if (connect (sock, (struct sockaddr *) &remote_address,
+                   sizeof (remote_address)) == -1)
+        {
+          request->logging_function (gftp_logging_error, request,
+                                     _("Cannot connect to %s: %s\n"),
+                                     connect_host, g_strerror (errno));
+        }
+      break;
+    }
+
+  if (host.h_addr_list[curhost] == NULL)
+    {
+      close (sock);
+      return (GFTP_ERETRYABLE);
+    }
+
+  return (sock);
+}
+
+
+int
+gftp_connect_server (gftp_request * request, char *service,
+                     char *proxy_hostname, unsigned int proxy_port)
+{
+  int sock;
+
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+  sock = gftp_connect_server_with_getaddr (request, service, proxy_hostname,
+                                           proxy_port);
+#else
+  sock = gftp_connect_server_legacy (request, service, proxy_hostname,
+                                     proxy_port);
+#endif
+
+  if (sock < 0)
+    return (sock);
+
+  if (fcntl (sock, F_SETFD, 1) == -1)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Error: Cannot set close on exec flag: %s\n"),
+                                 g_strerror (errno));
+      close (sock);
+      return (GFTP_ERETRYABLE);
+    }
+
+  if (gftp_fd_set_sockblocking (request, sock, 1) < 0)
+    {
+      close (sock);
+      return (GFTP_ERETRYABLE);
+    }
+
+  request->datafd = sock;
+
+  if (request->post_connect != NULL)
+    return (request->post_connect (request));
+
+  return (0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/sockutils.c	Tue Mar 04 12:28:40 2008 +0000
@@ -0,0 +1,360 @@
+/*****************************************************************************/
+/*  sockutils.c - various utilities for dealing with sockets                 */
+/*  Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org>                  */
+/*                                                                           */
+/*  This program is free software; you can redistribute it and/or modify     */
+/*  it under the terms of the GNU General Public License as published by     */
+/*  the Free Software Foundation; either version 2 of the License, or        */
+/*  (at your option) any later version.                                      */
+/*                                                                           */
+/*  This program is distributed in the hope that it will be useful,          */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
+/*  GNU General Public License for more details.                             */
+/*                                                                           */
+/*  You should have received a copy of the GNU General Public License        */
+/*  along with this program; if not, write to the Free Software              */
+/*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+ssize_t
+gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, 
+               char * str, size_t len, int fd)
+{
+  ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size,
+                            int fd);
+  char *pos, *nextpos;
+  size_t rlen, nslen;
+  int end_of_buffer;
+  ssize_t ret;
+
+  if (request == NULL || request->read_function == NULL)
+    read_function = gftp_fd_read;
+  else
+    read_function = request->read_function;
+
+  if (*rbuf == NULL)
+    {
+      *rbuf = g_malloc0 (sizeof (**rbuf));
+      (*rbuf)->max_bufsize = len;
+      (*rbuf)->buffer = g_malloc0 ((gulong) ((*rbuf)->max_bufsize + 1));
+
+      if ((ret = read_function (request, (*rbuf)->buffer, 
+                                (*rbuf)->max_bufsize, fd)) <= 0)
+        {
+          gftp_free_getline_buffer (rbuf);
+          return (ret);
+        }
+      (*rbuf)->buffer[ret] = '\0';
+      (*rbuf)->cur_bufsize = ret;
+      (*rbuf)->curpos = (*rbuf)->buffer;
+    }
+
+  ret = 0;
+  while (1)
+    {
+      pos = strchr ((*rbuf)->curpos, '\n');
+      end_of_buffer = (*rbuf)->curpos == (*rbuf)->buffer && 
+            ((*rbuf)->max_bufsize == (*rbuf)->cur_bufsize || (*rbuf)->eof);
+
+      if ((*rbuf)->cur_bufsize > 0 && (pos != NULL || end_of_buffer))
+        {
+          if (pos != NULL)
+            {
+              nslen = pos - (*rbuf)->curpos + 1;
+              nextpos = pos + 1;
+              if (pos > (*rbuf)->curpos && *(pos - 1) == '\r')
+                pos--;
+              *pos = '\0';
+            }
+          else
+            {
+              nslen = (*rbuf)->cur_bufsize;
+              nextpos = NULL;
+
+              /* This is not an overflow since we allocated one extra byte to
+                 buffer above */
+              ((*rbuf)->buffer)[nslen] = '\0';
+            }
+
+          strncpy (str, (*rbuf)->curpos, len);
+          str[len - 1] = '\0';
+          (*rbuf)->cur_bufsize -= nslen;
+
+          if (nextpos != NULL)
+            (*rbuf)->curpos = nextpos;
+          else
+            (*rbuf)->cur_bufsize = 0;
+
+          ret = nslen;
+          break;
+        }
+      else
+        {
+          if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0')
+            {
+              rlen = (*rbuf)->max_bufsize;
+              pos = (*rbuf)->buffer;
+            }
+          else
+            {
+              memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize);
+              pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize;
+              rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize;
+            }
+
+          (*rbuf)->curpos = (*rbuf)->buffer;
+
+          if ((*rbuf)->eof)
+            ret = 0;
+          else
+            {
+              ret = read_function (request, pos, rlen, fd);
+              if (ret < 0)
+                {
+                  gftp_free_getline_buffer (rbuf);
+                  return (ret);
+                }
+            }
+
+          if (ret == 0)
+            {
+              if ((*rbuf)->cur_bufsize == 0)
+                {
+                  gftp_free_getline_buffer (rbuf);
+                  return (ret);
+                }
+
+              (*rbuf)->eof = 1;
+            }
+
+          (*rbuf)->cur_bufsize += ret;
+          (*rbuf)->buffer[(*rbuf)->cur_bufsize] = '\0';
+        }
+    }
+
+  return (ret);
+}
+
+
+void
+gftp_free_getline_buffer (gftp_getline_buffer ** rbuf)
+{
+  g_free ((*rbuf)->buffer);
+  g_free (*rbuf);
+  *rbuf = NULL;
+}
+
+
+ssize_t 
+gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd)
+{
+  intptr_t network_timeout;
+  struct timeval tv;
+  fd_set fset;
+  ssize_t ret;
+  int s_ret;
+
+  g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
+
+  gftp_lookup_request_option (request, "network_timeout", &network_timeout);  
+
+  errno = 0;
+  ret = 0;
+  FD_ZERO (&fset);
+
+  do
+    {
+      FD_SET (fd, &fset);
+      tv.tv_sec = network_timeout;
+      tv.tv_usec = 0;
+      s_ret = select (fd + 1, &fset, NULL, NULL, &tv);
+      if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
+        {
+          if (request != NULL && request->cancel)
+            {
+              gftp_disconnect (request);
+              return (GFTP_ERETRYABLE);
+            }
+
+          continue;
+        }
+      else if (s_ret <= 0)
+        {
+          if (request != NULL)
+            {
+              request->logging_function (gftp_logging_error, request,
+                                         _("Connection to %s timed out\n"),
+                                         request->hostname);
+              gftp_disconnect (request);
+            }
+
+          return (GFTP_ERETRYABLE);
+        }
+
+      if ((ret = read (fd, ptr, size)) < 0)
+        {
+          if (errno == EINTR || errno == EAGAIN)
+            {
+              if (request != NULL && request->cancel)
+                {
+                  gftp_disconnect (request);
+                  return (GFTP_ERETRYABLE);
+                }
+
+              continue;
+            }
+ 
+          if (request != NULL)
+            {
+              request->logging_function (gftp_logging_error, request,
+                                   _("Error: Could not read from socket: %s\n"),
+                                    g_strerror (errno));
+              gftp_disconnect (request);
+            }
+
+          return (GFTP_ERETRYABLE);
+        }
+
+      break;
+    }
+  while (1);
+
+  return (ret);
+}
+
+
+ssize_t 
+gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd)
+{
+  intptr_t network_timeout;
+  struct timeval tv;
+  int ret, s_ret;
+  ssize_t w_ret;
+  fd_set fset;
+
+  g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
+
+  gftp_lookup_request_option (request, "network_timeout", &network_timeout);  
+
+  errno = 0;
+  ret = 0;
+  FD_ZERO (&fset);
+
+  do
+    {
+      FD_SET (fd, &fset);
+      tv.tv_sec = network_timeout;
+      tv.tv_usec = 0;
+      s_ret = select (fd + 1, NULL, &fset, NULL, &tv);
+      if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
+        {
+          if (request != NULL && request->cancel)
+            {
+              gftp_disconnect (request);
+              return (GFTP_ERETRYABLE);
+            }
+
+          continue;
+        }
+      else if (s_ret <= 0)
+        {
+          if (request != NULL)
+            {
+              request->logging_function (gftp_logging_error, request,
+                                         _("Connection to %s timed out\n"),
+                                         request->hostname);
+              gftp_disconnect (request);
+            }
+
+          return (GFTP_ERETRYABLE);
+        }
+
+      w_ret = write (fd, ptr, size);
+      if (w_ret < 0)
+        {
+          if (errno == EINTR || errno == EAGAIN)
+            {
+              if (request != NULL && request->cancel)
+                {
+                  gftp_disconnect (request);
+                  return (GFTP_ERETRYABLE);
+                }
+
+              continue;
+             }
+ 
+          if (request != NULL)
+            {
+              request->logging_function (gftp_logging_error, request,
+                                    _("Error: Could not write to socket: %s\n"),
+                                    g_strerror (errno));
+              gftp_disconnect (request);
+            }
+
+          return (GFTP_ERETRYABLE);
+        }
+
+      ptr += w_ret;
+      size -= w_ret;
+      ret += w_ret;
+    }
+  while (size > 0);
+
+  return (ret);
+}
+
+
+ssize_t 
+gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...)
+{
+  char *tempstr;
+  va_list argp;
+  ssize_t ret;
+
+  va_start (argp, fmt);
+  tempstr = g_strdup_vprintf (fmt, argp);
+  va_end (argp);
+
+  ret = request->write_function (request, tempstr, strlen (tempstr), fd);
+  g_free (tempstr);
+  return (ret);
+}
+
+
+int
+gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking)
+{
+  int flags;
+
+  g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
+
+  if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot get socket flags: %s\n"),
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (GFTP_ERETRYABLE);
+    }
+
+  if (non_blocking)
+    flags |= O_NONBLOCK;
+  else
+    flags &= ~O_NONBLOCK;
+
+  if (fcntl (fd, F_SETFL, flags) < 0)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot set socket to non-blocking: %s\n"),
+                                 g_strerror (errno));
+      gftp_disconnect (request);
+      return (GFTP_ERETRYABLE);
+    }
+
+  return (0);
+}
+