changeset 168:c505d9ba9d53

2003-6-6 Brian Masney <masneyb@gftp.org> * lib/gftp.h - if USE_SSL is defined, include the OpenSSL headers. Added read_function, write_function and post_connect function pointers to gftp_request structure. Added SSL object to gftp_request structure if USE_SSL is defined. Added protocol number and init function declarations for the HTTPS protocol * lib/options.h - added HTTPS to the list of supported protocols * lib/protocols.c lib/cache.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c - renamed gftp_read(), gftp_write() and gftp_set_sockblocking() to gftp_fd_read(), gftp_fd_write() and gftp_fd_set_sockblocking() respectively * lib/bookmark.c lib/local.c * lib/misc.c lib/rfc2068.c - moved base64_encode() to misc.c * lib/protocols.c - improved parsing of URLs. Rather than calling gftp_read() or gftp_write() directly, call the read_function or write_function that is set in the request structure. Expanded tabs to spaces. Cleanup for parsing of timestamps. In gftp_connect_server(), if a post_connect function pointer is set, call it after we are connected to the server. Improvements to gftp_get_line (). * lib/httpcommon.h lib/rfc2068.c - moved rfc2068_params structure to httpcommon.h. Fix for chunked file transfers, they were not handled at all before. Made the I/O calls a little more generic so that we can read from either a socket or a SSL connection. * lib/sslcommon.c - added generic SSL layer * lib/https.c - added support for the HTTPS protocol. It piggy backs off of the existing HTTP support and uses the generic SSL layer * src/gtk/bookmarks.c src/gtk/chmod_dialog.c src/gtk/gftp-gtk.c src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/options_dialog.c src/gtk/view_dialog.c - set the window icon name to the gFTP <version> * configure.in - added lib back to SUBDIRS (oops) * lib/Makefile.am - added https.c, sslcommon.c and httpcommon.h
author masneyb
date Sun, 08 Jun 2003 15:04:40 +0000
parents 4b767a186810
children d40f9db52cdf
files ChangeLog lib/Makefile.am lib/bookmark.c lib/cache.c lib/gftp.h lib/httpcommon.h lib/https.c lib/local.c lib/misc.c lib/options.h lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c lib/sslcommon.c src/gtk/bookmarks.c src/gtk/chmod_dialog.c src/gtk/gftp-gtk.c src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/options_dialog.c src/gtk/view_dialog.c
diffstat 22 files changed, 994 insertions(+), 307 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed May 28 18:37:28 2003 +0000
+++ b/ChangeLog	Sun Jun 08 15:04:40 2003 +0000
@@ -1,13 +1,57 @@
-2003-5-27 Brian Masney <masneyb@gftp.org>
-  * Makefile.am configure.in autogen.sh - build fixes
+2003-6-6 Brian Masney <masneyb@gftp.org>
+	* lib/gftp.h - if USE_SSL is defined, include the OpenSSL headers.
+	Added read_function, write_function and post_connect function pointers
+	to gftp_request structure. Added SSL object to gftp_request structure
+	if USE_SSL is defined. Added protocol number and init function
+	declarations for the HTTPS protocol
+
+	* lib/options.h - added HTTPS to the list of supported protocols
+
+	* lib/protocols.c lib/cache.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c -
+	renamed gftp_read(), gftp_write() and gftp_set_sockblocking() to 
+	gftp_fd_read(), gftp_fd_write() and gftp_fd_set_sockblocking()
+	respectively
+
+	* lib/bookmark.c lib/local.c 
+
+	* lib/misc.c lib/rfc2068.c - moved base64_encode() to misc.c
 
-  * src/text/gftp-text.c - if the protocol we are connecting to
-  doesn't need a username/password, don't prompt the user for one
+	* lib/protocols.c - improved parsing of URLs. Rather than calling
+	gftp_read() or gftp_write() directly, call the read_function or
+	write_function that is set in the request structure. Expanded tabs 
+	to spaces. Cleanup for parsing of timestamps. In
+	gftp_connect_server(), if a post_connect function pointer is set,
+	call it after we are connected to the server. Improvements to
+	gftp_get_line (). 
+
+	* lib/httpcommon.h lib/rfc2068.c - moved rfc2068_params structure to
+	httpcommon.h. Fix for chunked file transfers, they were not handled 
+	at all before. Made the I/O calls a little more generic so that we can
+	read from either a socket or a SSL connection.
+
+	* lib/sslcommon.c - added generic SSL layer
+
+	* lib/https.c - added support for the HTTPS protocol. It piggy backs
+	off of the existing HTTP support and uses the generic SSL layer
+
+	* src/gtk/bookmarks.c src/gtk/chmod_dialog.c src/gtk/gftp-gtk.c
+	src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/options_dialog.c 
+	src/gtk/view_dialog.c - set the window icon name to the gFTP <version>
+
+	* configure.in - added lib back to SUBDIRS (oops)
+
+	* lib/Makefile.am - added https.c, sslcommon.c and httpcommon.h
+
+2003-5-27 Brian Masney <masneyb@gftp.org>
+	* Makefile.am configure.in autogen.sh - build fixes
+
+	* src/text/gftp-text.c - if the protocol we are connecting to
+	  doesn't need a username/password, don't prompt the user for one
 
 2003-5-22 Brian Masney <masneyb@gftp.org>
-  * lib/misc.c (gftp_usage) - updated usage statement
+	* lib/misc.c (gftp_usage) - updated usage statement
 
-  * lib/options.h - put terminate options properly
+	* lib/options.h - put terminate options properly
 
 2003-05-06  Christian Rose  <menthos@menthos.com>
 
@@ -837,7 +881,7 @@
 
 	* cvsclean - added this script
 
-	* *.[ch] - added $Id: ChangeLog,v 1.80 2003/05/27 18:03:19 masneyb Exp $ tags
+	* *.[ch] - added $Id: ChangeLog,v 1.81 2003/06/08 15:04:37 masneyb Exp $ tags
 
 	* debian/* - updated files from Debian maintainer
 
--- a/lib/Makefile.am	Wed May 28 18:37:28 2003 +0000
+++ b/lib/Makefile.am	Sun Jun 08 15:04:40 2003 +0000
@@ -1,7 +1,7 @@
 ## Process this file with automake to produce Makefile.in 
 
 noinst_LIBRARIES = libgftp.a
-libgftp_a_SOURCES=bookmark.c cache.c config_file.c local.c misc.c protocols.c \
-                  pty.c rfc959.c rfc2068.c sshv2.c
+libgftp_a_SOURCES=bookmark.c cache.c config_file.c https.c local.c misc.c \
+                  protocols.c pty.c rfc959.c rfc2068.c sshv2.c sslcommon.c
 INCLUDES=@GLIB_CFLAGS@ @PTHREAD_CFLAGS@ -I../intl -DSHARE_DIR=\"$(datadir)/gftp\" 
-noinst_HEADERS=gftp.h options.h
+noinst_HEADERS=gftp.h httpcommon.h options.h
--- a/lib/bookmark.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/bookmark.c	Sun Jun 08 15:04:40 2003 +0000
@@ -59,8 +59,11 @@
 
   request->protonum = GFTP_BOOKMARK_NUM;
   request->init = bookmark_init;
+  request->read_function = NULL;
+  request->write_function = NULL;
   request->destroy = NULL;
   request->connect = NULL;
+  request->post_connect = NULL;
   request->disconnect = NULL;
   request->get_file = NULL;
   request->put_file = NULL;
--- a/lib/cache.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/cache.c	Sun Jun 08 15:04:40 2003 +0000
@@ -140,7 +140,7 @@
                            request->directory == NULL ? "" : request->directory,
                            tempstr, request->server_type);
   g_free (tempstr);
-  ret = gftp_write (NULL, temp1str, strlen (temp1str), fd);
+  ret = gftp_fd_write (NULL, temp1str, strlen (temp1str), fd);
   g_free (temp1str);
 
   if (close (fd) != 0 || ret < 0)
@@ -333,7 +333,7 @@
              as we read it */
           gftp_restore_cache_line (&centry, buf);
 
-          if (gftp_write (NULL, buf, strlen (buf), newfd) < 0)
+          if (gftp_fd_write (NULL, buf, strlen (buf), newfd) < 0)
             break;
         }
     }
--- a/lib/gftp.h	Wed May 28 18:37:28 2003 +0000
+++ b/lib/gftp.h	Sun Jun 08 15:04:40 2003 +0000
@@ -67,6 +67,14 @@
 #include <strings.h>
 #endif
 
+#ifdef USE_SSL
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+#endif
+
 #ifdef ENABLE_NLS
 #include <libintl.h>
 #include <locale.h>
@@ -334,8 +342,17 @@
   void *user_data;
 
   void (*init)				( gftp_request * request );
+  ssize_t (*read_function)		( gftp_request * request,
+					  void *ptr, 
+					  size_t size, 
+					  int fd );
+  ssize_t (*write_function)		( gftp_request * request, 
+					  const char *ptr, 
+					  size_t size, 
+					  int fd );
   void (*destroy)			( gftp_request * request );
   int (*connect)			( gftp_request * request );
+  int (*post_connect)			( gftp_request * request );
   void (*disconnect) 			( gftp_request * request );
   off_t (*get_file) 			( gftp_request * request, 
 					  const char *filename, 
@@ -394,6 +411,9 @@
   gftp_config_vars * local_options_vars;
   int num_local_options_vars;
   GHashTable * local_options_hash;
+#ifdef USE_SSL
+  SSL * ssl;
+#endif
 };
 
 
@@ -634,12 +654,15 @@
 					  char *file_prefixstr, 
 					  char *file_suffixstr );
 
+char * base64_encode 			( char *str );
+
 /* protocols.c */
 #define GFTP_FTP_NUM				0
 #define GFTP_HTTP_NUM				1
-#define GFTP_LOCAL_NUM				2
-#define GFTP_SSHV2_NUM				3
-#define GFTP_BOOKMARK_NUM			4
+#define GFTP_HTTPS_NUM				2
+#define GFTP_LOCAL_NUM				3
+#define GFTP_SSHV2_NUM				4
+#define GFTP_BOOKMARK_NUM			5
 
 #define GFTP_IS_CONNECTED(request)		((request) != NULL && \
                                                  ((request)->sockfd > 0 || \
@@ -659,6 +682,10 @@
 
 void rfc2068_register_module		( void );
 
+void https_init 			( gftp_request * request );
+
+void https_register_module		( void );
+
 void local_init 			( gftp_request * request );
 
 void local_register_module		( void );
@@ -807,18 +834,19 @@
 
 void print_file_list 			( GList * list );
 
+
 ssize_t gftp_get_line 			( gftp_request * request, 
 					  gftp_getline_buffer ** rbuf,
 					  char * str, 
 					  size_t len, 
 					  int fd );
 
-ssize_t gftp_read 			( gftp_request * request, 
+ssize_t gftp_fd_read 			( gftp_request * request, 
 					  void *ptr, 
 					  size_t size, 
 					  int fd );
 
-ssize_t gftp_write 			( gftp_request * request, 
+ssize_t gftp_fd_write 			( gftp_request * request, 
 					  const char *ptr, 
 					  size_t size, 
 					  int fd );
@@ -828,7 +856,7 @@
 					  const char *fmt, 
 					  ... );
 
-int gftp_set_sockblocking 		( gftp_request * request, 
+int gftp_fd_set_sockblocking 		( gftp_request * request, 
 					  int fd, 
 					  int non_blocking );
 
@@ -848,5 +876,24 @@
 
 int tty_raw 				( int fd );
 
+#ifdef USE_SSL
+/* sslcommon.c */
+int gftp_ssl_startup 			( gftp_request * request );
+
+int gftp_ssl_session_setup 		( gftp_request * request );
+
+void gftp_ssl_free 			( gftp_request * request );
+
+ssize_t gftp_ssl_read 			( gftp_request * request, 
+					  void *ptr, 
+					  size_t size, 
+					  int fd );
+
+ssize_t gftp_ssl_write 			( gftp_request * request, 
+					  const char *ptr, 
+					  size_t size, 
+					  int fd );
+#endif /* USE_SSL */
+
 #endif
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/httpcommon.h	Sun Jun 08 15:04:40 2003 +0000
@@ -0,0 +1,40 @@
+/*****************************************************************************/
+/*  httpcommon.h - common data structures for RFC2068 and HTTPS              */
+/*  Copyright (C) 1998-2003 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., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+/*****************************************************************************/
+
+/* $Id$ */
+
+typedef struct rfc2068_params_tag
+{
+  gftp_getline_buffer * rbuf;
+  unsigned long read_bytes,
+                content_length,
+                chunk_size;
+  unsigned int chunked_transfer : 1;
+  ssize_t (*real_read_function) ( gftp_request * request,
+                                  void *ptr,
+                                  size_t size,
+                                  int fd );
+
+} rfc2068_params;
+
+int rfc2068_get_next_file 			( gftp_request * request,
+						  gftp_file * fle,
+						  int fd );
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/https.c	Sun Jun 08 15:04:40 2003 +0000
@@ -0,0 +1,76 @@
+/*****************************************************************************/
+/*  https.c - General purpose routines for the HTTPS protocol                */
+/*  Copyright (C) 1998-2003 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"
+#include "httpcommon.h"
+
+static const char cvsid[] = "$Id$";
+
+static int
+https_get_next_file (gftp_request * request, gftp_file * fle, int fd)
+{
+  rfc2068_params * params;
+  int ret, resetptr;
+
+  params = request->protocol_data;
+  if (request->cached)
+    {
+      params->real_read_function = gftp_fd_read;
+      request->write_function = gftp_fd_write;
+      resetptr = 1;
+    }
+  else
+    resetptr = 0;
+
+  ret = rfc2068_get_next_file (request, fle, fd);
+
+  if (resetptr)
+    {
+      params->real_read_function = gftp_ssl_read;
+      request->write_function = gftp_ssl_write;
+    }
+
+  return (ret);
+}
+
+
+void
+https_register_module (void)
+{
+  gftp_ssl_startup (NULL); /* FIXME - take out of here */
+}
+
+
+void
+https_init (gftp_request * request)
+{
+  rfc2068_params * params;
+
+  g_return_if_fail (request != NULL);
+
+  gftp_protocols[GFTP_HTTP_NUM].init (request);
+  params = request->protocol_data;
+  request->init = https_init;
+  request->post_connect = gftp_ssl_session_setup;
+  params->real_read_function = gftp_ssl_read;
+  request->write_function = gftp_ssl_write;
+  request->get_next_file = https_get_next_file;
+  request->url_prefix = g_strdup ("https");
+}
+
--- a/lib/local.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/local.c	Sun Jun 08 15:04:40 2003 +0000
@@ -647,7 +647,10 @@
   request->protonum = GFTP_LOCAL_NUM;
   request->init = local_init;
   request->destroy = local_destroy;
+  request->read_function = gftp_fd_read;
+  request->write_function = gftp_fd_write;
   request->connect = local_connect;
+  request->post_connect = NULL;
   request->disconnect = local_disconnect;
   request->get_file = local_get_file;
   request->put_file = local_put_file;
--- a/lib/misc.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/misc.c	Sun Jun 08 15:04:40 2003 +0000
@@ -529,10 +529,8 @@
   gftp_transfer * tdata;
 
   tdata = g_malloc0 (sizeof (*tdata));
-/* FIXME
-  tdata->statmutex = G_STATIC_MUTEX_INIT;
-  tdata->structmutex = G_STATIC_MUTEX_INIT;
-*/
+  g_static_mutex_init (&tdata->statmutex);
+  g_static_mutex_init (&tdata->structmutex);
   return (tdata);
 }
 
@@ -989,3 +987,51 @@
   return (sent);
 }
 
+
+char *
+base64_encode (char *str)
+{
+
+/* The standard to Base64 encoding can be found in RFC2045 */
+
+  char *newstr, *newpos, *fillpos, *pos;
+  unsigned char table[64], encode[3];
+  int i, num;
+
+  for (i = 0; i < 26; i++)
+    {
+      table[i] = 'A' + i;
+      table[i + 26] = 'a' + i;
+    }
+
+  for (i = 0; i < 10; i++)
+    table[i + 52] = '0' + i;
+
+  table[62] = '+';
+  table[63] = '-';
+
+  num = strlen (str) / 3;
+  if (strlen (str) % 3 > 0)
+    num++;
+  newstr = g_malloc (num * 4 + 1);
+  newstr[num * 4] = '\0';
+  newpos = newstr;
+
+  pos = str;
+  while (*pos != '\0')
+    {
+      memset (encode, 0, sizeof (encode));
+      for (i = 0; i < 3 && *pos != '\0'; i++)
+	encode[i] = *pos++;
+
+      fillpos = newpos;
+      *newpos++ = table[encode[0] >> 2];
+      *newpos++ = table[(encode[0] & 3) << 4 | encode[1] >> 4];
+      *newpos++ = table[(encode[1] & 0xF) << 2 | encode[2] >> 6];
+      *newpos++ = table[encode[2] & 0x3F];
+      while (i < 3)
+	fillpos[++i] = '=';
+    }
+  return (newstr);
+}
+
--- a/lib/options.h	Wed May 28 18:37:28 2003 +0000
+++ b/lib/options.h	Sun Jun 08 15:04:40 2003 +0000
@@ -179,6 +179,7 @@
 {
   {N_("FTP"), rfc959_init, rfc959_register_module, "ftp", 1},
   {N_("HTTP"), rfc2068_init, rfc2068_register_module, "http", 1},
+  {N_("HTTPS"), https_init, https_register_module, "https", 1},
   {N_("Local"), local_init, local_register_module, "file", 1},
   {N_("SSH2"), sshv2_init, sshv2_register_module, "ssh2", 1},
   {N_("Bookmark"), bookmark_init, bookmark_register_module, "bookmark", 0},
--- a/lib/protocols.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/protocols.c	Sun Jun 08 15:04:40 2003 +0000
@@ -128,6 +128,14 @@
 #endif
   request->hostp = NULL;
 
+#ifdef USE_SSL
+  if (request->ssl != NULL)
+    {
+      SSL_free (request->ssl);
+      request->ssl = NULL;
+    }
+#endif
+
   request->cached = 0;
   if (request->disconnect == NULL)
     return;
@@ -227,7 +235,7 @@
   if (request->get_next_file_chunk != NULL)
     return (request->get_next_file_chunk (request, buf, size));
 
-  return (gftp_read (request, buf, size, request->datafd));
+  return (request->read_function (request, buf, size, request->datafd));
 }
 
 
@@ -243,7 +251,7 @@
   if (size == 0)
     return (0);
 
-  return (gftp_write (request, buf, size, request->datafd));
+  return (request->write_function (request, buf, size, request->datafd));
 }
 
 
@@ -364,7 +372,7 @@
       if (ret >= 0 && !request->cached && request->cachefd > 0 && 
           request->last_dir_entry != NULL)
         {
-          if (gftp_write (request, request->last_dir_entry,
+          if (gftp_fd_write (request, request->last_dir_entry,
                           request->last_dir_entry_len, request->cachefd) < 0)
             {
               request->logging_function (gftp_logging_error, request->user_data,
@@ -458,9 +466,9 @@
 int
 gftp_parse_url (gftp_request * request, const char *url)
 {
-  char *pos, *endpos, *endhostpos, *str, tempchar, *default_protocol;
+  char *pos, *endpos, *endhostpos, tempchar, *default_protocol, *stpos;
   gftp_logging_func logging_function;
-  const char *stpos;
+  const char *cpos;
   int len, i;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
@@ -470,7 +478,10 @@
   gftp_request_destroy (request, 0);
   request->logging_function = logging_function;
 
-  for (stpos = url; *stpos == ' '; stpos++);
+  for (cpos = url; *cpos == ' '; cpos++);
+  stpos = g_strdup (cpos);
+  for (pos = stpos + strlen (stpos) - 1; *pos == ' '; pos--)
+    *pos = '\0';
 
   i = GFTP_FTP_NUM;
 
@@ -484,9 +495,13 @@
             break;
         }
 
+      *pos = ':';
+
       if (gftp_protocols[i].url_prefix == NULL)
-        return (GFTP_EFATAL);
-      *pos = ':';
+        {
+          g_free (stpos);
+          return (GFTP_EFATAL);
+        }
     }
   else
     {
@@ -509,48 +524,47 @@
   gftp_protocols[i].init (request);
 
   if (request->parse_url != NULL)
-    return (request->parse_url (request, url));
+    {
+      g_free (stpos);
+      return (request->parse_url (request, url));
+    }
+
+  pos = stpos;
+  len = strlen (request->url_prefix);
+  if (strncmp (pos, request->url_prefix, len) == 0 && 
+      strncmp (pos + len, "://", 3) == 0)
+    pos += len + 3;
 
   if (i == GFTP_LOCAL_NUM)
     {
-      request->directory = g_strdup (stpos + 7);
+      request->directory = g_strdup (pos);
+      g_free (stpos);
       return (0);
     }
 
-  for (; *stpos == ' '; stpos++);
-  str = g_strdup (stpos);
-  for (pos = str + strlen (str) - 1; *pos == ' '; pos--)
-    *pos = '\0';
-
-  pos = str;
-  len = strlen (request->url_prefix);
-  if (strncmp (pos, request->url_prefix, len) == 0
-      && strncmp (pos + len, "://", 3) == 0)
-    pos += len + 3;
-
   if ((endhostpos = strchr (pos, '@')) != NULL)
     {
       /* A user/password was entered */
       if ((endpos = strchr (pos, ':')) == NULL || endhostpos < endpos)
-	{
-	  /* No password was entered */
-	  gftp_set_password (request, "");
-	  endpos = endhostpos;
-	}
+        {
+          /* No password was entered */
+          gftp_set_password (request, "");
+          endpos = endhostpos;
+        }
 
       *endpos = '\0';
       gftp_set_username (request, pos);
 
       pos = endpos + 1;
       if ((endpos = strchr (pos, '@')) != NULL)
-	{
-	  if (strchr (endpos + 1, '@') != NULL)
-	    endpos = strchr (endpos + 1, '@');
-	  *endpos = '\0';
-	  gftp_set_password (request, pos);
+        {
+          if (strchr (endpos + 1, '@') != NULL)
+            endpos = strchr (endpos + 1, '@');
+          *endpos = '\0';
+          gftp_set_password (request, pos);
 
-	  pos = endpos + 1;
-	}
+          pos = endpos + 1;
+        }
     }
 
   /* Now get the hostname and an optional port and optional directory */
@@ -572,7 +586,7 @@
     }
   if ((endpos = strchr (pos, '/')) != NULL)
     gftp_set_directory (request, endpos);
-  g_free (str);
+  g_free (stpos);
   return (0);
 }
 
@@ -635,11 +649,11 @@
   if (request->sockfd <= 0 && !request->always_connected)
     {
       if (directory != request->directory)
-	{
-	  if (request->directory)
-	    g_free (request->directory);
-	  request->directory = g_strdup (directory);
-	}
+        {
+          if (request->directory)
+            g_free (request->directory);
+          request->directory = g_strdup (directory);
+        }
       return (0);
     }
   else if (request->chdir == NULL)
@@ -692,7 +706,7 @@
 
 int
 gftp_rename_file (gftp_request * request, const char *oldname,
-		  const char *newname)
+                  const char *newname)
 {
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
 
@@ -822,23 +836,23 @@
       hostname = templist->data;
       if (hostname->domain && 
           strlen (request->hostname) > strlen (hostname->domain))
-	{
-	  pos = request->hostname + strlen (request->hostname) -
-	                         strlen (hostname->domain);
-	  if (strcmp (hostname->domain, pos) == 0)
-	    return (0);
-	}
+        {
+          pos = request->hostname + strlen (request->hostname) -
+                                 strlen (hostname->domain);
+          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)) & 
+        {
+          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);
-	}
+          if (netaddr == hostname->ipv4_network_address)
+            return (0);
+        }
       templist = templist->next;
     }
 
@@ -894,6 +908,7 @@
   struct tm curtime, *loctime;
   time_t t, ret;
   char *tmppos;
+  int i;
 
   memset (&curtime, 0, sizeof (curtime));
   curtime.tm_isdst = -1;
@@ -937,7 +952,8 @@
           /* 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 */
 
-          for (*endpos = str; **endpos != ' ' && **endpos != '\t' && **endpos != '\0'; *endpos++);
+          for (i=0, *endpos = str; (*endpos)[i] != ' ' && (*endpos)[i] != '\t' && (*endpos)[i] != '\0'; i++);
+          endpos += i;
         }
       else
         *endpos = tmppos;
@@ -1033,17 +1049,17 @@
     {
       startpos++;
       switch (*startpos)
-	{
-	case '/':
-	  *fle->attribs = 'd';
-	  break;
-	case 's':
-	  fle->size = strtol (startpos + 1, NULL, 10);
-	  break;
-	case 'm':
-	  fle->datetime = strtol (startpos + 1, NULL, 10);
-	  break;
-	}
+        {
+        case '/':
+          *fle->attribs = 'd';
+          break;
+        case 's':
+          fle->size = strtol (startpos + 1, NULL, 10);
+          break;
+        case 'm':
+          fle->datetime = strtol (startpos + 1, NULL, 10);
+          break;
+        }
       startpos = strchr (startpos, ',');
     }
   if ((startpos = strchr (str, 9)) == NULL)
@@ -1101,20 +1117,20 @@
 
       /* Copy the user that owns this file */
       if ((startpos = copy_token (&fle->user, startpos)) == NULL)
-	return (GFTP_EFATAL);
+        return (GFTP_EFATAL);
 
       /* Copy the group that owns this file */
       if ((startpos = copy_token (&fle->group, startpos)) == NULL)
-	return (GFTP_EFATAL);
+        return (GFTP_EFATAL);
     }
   else
     {
       fle->group = g_strdup (_("unknown"));
       if (cols == 8)
-	{
-	  if ((startpos = copy_token (&fle->user, startpos)) == NULL)
-	    return (GFTP_EFATAL);
-	}
+        {
+          if ((startpos = copy_token (&fle->user, startpos)) == NULL)
+            return (GFTP_EFATAL);
+        }
       else
         fle->user = g_strdup (_("unknown"));
       startpos = goto_next_token (startpos);
@@ -1141,18 +1157,18 @@
 
       startpos = endpos + 1;
       while (*startpos == ' ')
-	startpos++;
+        startpos++;
 
       /* Get the minor number */
       if ((endpos = strchr (startpos, ' ')) == NULL)
-	return (GFTP_EFATAL);
+        return (GFTP_EFATAL);
       fle->size |= strtol (startpos, NULL, 10) & 0xFF;
     }
   else
     {
       /* This is a regular file  */
       if ((endpos = strchr (startpos, ' ')) == NULL)
-	return (GFTP_EFATAL);
+        return (GFTP_EFATAL);
       fle->size = strtol (startpos, NULL, 10);
     }
 
@@ -1599,15 +1615,15 @@
         snprintf (serv, sizeof (serv), "%d", port);
 
       request->logging_function (gftp_logging_misc, request->user_data,
-				 _("Looking up %s\n"), connect_host);
+                                 _("Looking up %s\n"), connect_host);
       if ((errnum = getaddrinfo (connect_host, serv, &hints, 
                                  &request->hostp)) != 0)
-	{
-	  request->logging_function (gftp_logging_error, request->user_data,
-				     _("Cannot look up hostname %s: %s\n"),
-				     connect_host, gai_strerror (errnum));
-	  return (GFTP_ERETRYABLE);
-	}
+        {
+          request->logging_function (gftp_logging_error, request->user_data,
+                                     _("Cannot look up hostname %s: %s\n"),
+                                     connect_host, gai_strerror (errnum));
+          return (GFTP_ERETRYABLE);
+        }
     }
 
   disphost = connect_host;
@@ -1621,23 +1637,23 @@
       if ((sock = socket (res->ai_family, res->ai_socktype, 
                           res->ai_protocol)) < 0)
         {
-	  request->logging_function (gftp_logging_error, request->user_data,
+          request->logging_function (gftp_logging_error, request->user_data,
                                      _("Failed to create a socket: %s\n"),
                                      g_strerror (errno));
           continue; 
         } 
 
       request->logging_function (gftp_logging_misc, request->user_data,
-				 _("Trying %s:%d\n"), disphost, port);
+                                 _("Trying %s:%d\n"), disphost, port);
 
       if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
-	{
-	  request->logging_function (gftp_logging_error, request->user_data,
-				     _("Cannot connect to %s: %s\n"),
-				     disphost, g_strerror (errno));
+        {
+          request->logging_function (gftp_logging_error, request->user_data,
+                                     _("Cannot connect to %s: %s\n"),
+                                     disphost, g_strerror (errno));
           close (sock);
           continue;
-	}
+        }
       break;
     }
 
@@ -1708,7 +1724,7 @@
   if (request->hostp == NULL)
     {
       request->logging_function (gftp_logging_misc, request->user_data,
-				 _("Looking up %s\n"), connect_host);
+                                 _("Looking up %s\n"), connect_host);
       if (!(request->hostp = r_gethostbyname (connect_host, &request->host,
                                               NULL)))
         {
@@ -1749,15 +1765,20 @@
 #endif /* HAVE_GETADDRINFO */
 
   request->logging_function (gftp_logging_misc, request->user_data,
-			     _("Connected to %s:%d\n"), connect_host, port);
+                             _("Connected to %s:%d\n"), connect_host, port);
 
-  if (gftp_set_sockblocking (request, sock, 1) < 0)
+  if (gftp_fd_set_sockblocking (request, sock, 1) < 0)
     {
       close (sock);
       return (GFTP_ERETRYABLE);
     }
 
-  return (sock);
+  request->sockfd = sock;
+
+  if (request->post_connect != NULL)
+    return (request->post_connect (request));
+
+  return (0);
 }
 
 
@@ -1823,27 +1844,35 @@
 gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, 
                char * str, size_t len, int fd)
 {
-  ssize_t ret, retval, rlen, copysize;
+  ssize_t ret, retval, rlen;
   char *pos, *nextpos;
+  ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size,
+                            int fd);
+
+  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_malloc ((*rbuf)->max_bufsize + 1);
-      if ((ret = gftp_read (request, (*rbuf)->buffer, (*rbuf)->max_bufsize, 
-                            fd)) <= 0)
+
+      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;
     }
 
   retval = GFTP_ERETRYABLE;
-
   do
     {
       if ((*rbuf)->cur_bufsize > 0 &&
@@ -1852,6 +1881,11 @@
             (*rbuf)->max_bufsize == (*rbuf)->cur_bufsize)))
         {
           if (pos != NULL)
+            retval = pos - (*rbuf)->curpos + 1;
+          else
+            retval = (*rbuf)->cur_bufsize;
+
+          if (pos != NULL)
             {
               nextpos = pos + 1;
               if (pos > (*rbuf)->curpos && *(pos - 1) == '\r')
@@ -1862,16 +1896,12 @@
             nextpos = NULL;
 
           strncpy (str, (*rbuf)->curpos, len);
-          retval = pos - (*rbuf)->curpos > len ? len : pos - (*rbuf)->curpos;
+          (*rbuf)->cur_bufsize -= retval;
 
-          if (pos != NULL)
-            {
-              if (nextpos - (*rbuf)->buffer >= (*rbuf)->cur_bufsize)
-                (*rbuf)->cur_bufsize = 0;
-              else
-                (*rbuf)->curpos = nextpos;
-            }
-
+          if (nextpos != NULL)
+            (*rbuf)->curpos = nextpos;
+          else
+            (*rbuf)->cur_bufsize = 0;
           break;
         }
       else
@@ -1880,24 +1910,29 @@
             {
               rlen = (*rbuf)->max_bufsize;
               pos = (*rbuf)->buffer;
-              copysize = 0;
             }
           else
             {
-              copysize = (*rbuf)->cur_bufsize - ((*rbuf)->curpos - (*rbuf)->buffer);
-              memmove ((*rbuf)->buffer, (*rbuf)->curpos, copysize);
-              pos = (*rbuf)->buffer + copysize;
-              rlen = (*rbuf)->max_bufsize - copysize;
+              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 ((ret = gftp_read (request, pos, rlen, fd)) <= 0)
+          if ((ret = read_function (request, pos, rlen, fd)) < 0)
             {
               gftp_free_getline_buffer (rbuf);
               return (ret);
             }
-          (*rbuf)->buffer[ret + copysize] = '\0';
-          (*rbuf)->cur_bufsize = ret + copysize;
+          else if (ret == 0 && (*rbuf)->cur_bufsize == 0)
+            {
+              gftp_free_getline_buffer (rbuf);
+              return (ret);
+            }
+
+          (*rbuf)->buffer[ret + (*rbuf)->cur_bufsize] = '\0';
+          (*rbuf)->cur_bufsize += ret;
         }
     }
   while (retval == GFTP_ERETRYABLE);
@@ -1907,7 +1942,7 @@
 
 
 ssize_t 
-gftp_read (gftp_request * request, void *ptr, size_t size, int fd)
+gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd)
 {
   long network_timeout;
   struct timeval tv;
@@ -1977,7 +2012,7 @@
 
 
 ssize_t 
-gftp_write (gftp_request * request, const char *ptr, size_t size, int fd)
+gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd)
 {
   long network_timeout;
   struct timeval tv;
@@ -2061,14 +2096,14 @@
   tempstr = g_strdup_vprintf (fmt, argp);
   va_end (argp);
 
-  ret = gftp_write (request, tempstr, strlen (tempstr), fd);
+  ret = request->write_function (request, tempstr, strlen (tempstr), fd);
   g_free (tempstr);
   return (ret);
 }
 
 
 int
-gftp_set_sockblocking (gftp_request * request, int fd, int non_blocking)
+gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking)
 {
   int flags;
 
--- a/lib/rfc2068.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/rfc2068.c	Sun Jun 08 15:04:40 2003 +0000
@@ -18,6 +18,8 @@
 /*****************************************************************************/
 
 #include "gftp.h"
+#include "httpcommon.h"
+
 static const char cvsid[] = "$Id$";
 
 static gftp_config_vars config_vars[] =
@@ -44,75 +46,20 @@
   {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
 };
 
-typedef struct rfc2068_params_tag
-{
-  gftp_getline_buffer * rbuf;
-  unsigned long read_bytes,
-                max_bytes;
-  int chunked_transfer : 1;
-} rfc2068_params;
-
-
-static char *
-base64_encode (char *str)
-{
-
-/* The standard to Base64 encoding can be found in RFC2045 */
-
-  char *newstr, *newpos, *fillpos, *pos;
-  unsigned char table[64], encode[3];
-  int i, num;
-
-  for (i = 0; i < 26; i++)
-    {
-      table[i] = 'A' + i;
-      table[i + 26] = 'a' + i;
-    }
-
-  for (i = 0; i < 10; i++)
-    table[i + 52] = '0' + i;
-
-  table[62] = '+';
-  table[63] = '-';
-
-  num = strlen (str) / 3;
-  if (strlen (str) % 3 > 0)
-    num++;
-  newstr = g_malloc (num * 4 + 1);
-  newstr[num * 4] = '\0';
-  newpos = newstr;
-
-  pos = str;
-  while (*pos != '\0')
-    {
-      memset (encode, 0, sizeof (encode));
-      for (i = 0; i < 3 && *pos != '\0'; i++)
-	encode[i] = *pos++;
-
-      fillpos = newpos;
-      *newpos++ = table[encode[0] >> 2];
-      *newpos++ = table[(encode[0] & 3) << 4 | encode[1] >> 4];
-      *newpos++ = table[(encode[1] & 0xF) << 2 | encode[2] >> 6];
-      *newpos++ = table[encode[2] & 0x3F];
-      while (i < 3)
-	fillpos[++i] = '=';
-    }
-  return (newstr);
-}
-
 
 static off_t 
 rfc2068_read_response (gftp_request * request)
 {
   rfc2068_params * params;
-  char tempstr[255];
-  int ret;
+  char tempstr[512];
+  int ret, chunked;
 
   params = request->protocol_data;
-  params->chunked_transfer = 0;
+  chunked = 0;
+  params->chunk_size = 0;
   params->rbuf = NULL;
   *tempstr = '\0';
-  params->max_bytes = 0;
+  params->content_length = 0;
   if (request->last_ftp_response)
     {
       g_free (request->last_ftp_response); 
@@ -121,8 +68,8 @@
 
   do
     {
-      if ((ret = gftp_get_line (request, &params->rbuf, tempstr, sizeof (tempstr), 
-                                request->sockfd)) < 0)
+      if ((ret = gftp_get_line (request, &params->rbuf, tempstr, 
+                                sizeof (tempstr), request->sockfd)) < 0)
         return (ret);
 
       if (request->last_ftp_response == NULL)
@@ -134,20 +81,48 @@
                                      tempstr);
 
           if (strncmp (tempstr, "Content-Length:", 15) == 0)
-            params->max_bytes = strtol (tempstr + 16, NULL, 10);
-          if (strcmp (tempstr, "Transfer-Encoding: chunked") == 0)
-            params->chunked_transfer = 1;
+            params->content_length = strtol (tempstr + 16, NULL, 10);
+          else if (strcmp (tempstr, "Transfer-Encoding: chunked") == 0)
+            chunked = 1;
         }
     }
   while (*tempstr != '\0');
 
-  return (params->max_bytes);
+  if (chunked)
+    {
+      if ((ret = gftp_get_line (request, &params->rbuf, tempstr, 
+                                sizeof (tempstr), request->sockfd)) < 0)
+        return (ret);
+
+      if (sscanf ((char *) tempstr, "%lx", &params->chunk_size) != 1)
+        {
+          request->logging_function (gftp_logging_recv, request->user_data,
+                                     _("Received wrong response from server, disconnecting\n"));
+          gftp_disconnect (request);
+          return (GFTP_EFATAL);
+        }
+
+      if (params->chunk_size == 0)
+        return (0);
+
+      params->chunk_size -= params->rbuf->cur_bufsize;
+
+      if (params->chunk_size < 0)
+        {
+          request->logging_function (gftp_logging_recv, request->user_data, "FIXME - the chunk size is negative. aborting directory listing\n");
+          return (GFTP_EFATAL);
+        }
+
+        
+    }
+
+  params->chunked_transfer = chunked;
+  return (params->content_length > 0 ? params->content_length : params->chunk_size);
 }
 
 
 static off_t 
-rfc2068_send_command (gftp_request * request, const char *command,
-                      const char *extrahdr)
+rfc2068_send_command (gftp_request * request, const void *command, size_t len)
 {
   char *tempstr, *str, *proxy_hostname, *proxy_username, *proxy_password;
   int proxy_port;
@@ -157,13 +132,14 @@
   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL);
   g_return_val_if_fail (command != NULL, GFTP_EFATAL);
 
-  tempstr = g_strdup_printf ("%sUser-Agent: %s\nHost: %s\n", command,
+  tempstr = g_strdup_printf ("%sUser-Agent: %s\nHost: %s\n", (char *) command,
                              gftp_version, request->hostname);
 
   request->logging_function (gftp_logging_send, request->user_data,
                              "%s", tempstr);
 
-  ret = gftp_write (request, tempstr, strlen (tempstr), request->sockfd);
+  ret = request->write_function (request, tempstr, strlen (tempstr), 
+                                 request->sockfd);
   g_free (tempstr);
 
   if (ret < 0)
@@ -186,7 +162,7 @@
                            "Proxy-authorization: Basic %s\n", str);
       g_free (str);
       if (ret < 0)
-	return (ret);
+        return (ret);
     }
 
   if (request->username != NULL && *request->username != '\0')
@@ -201,19 +177,10 @@
                            "Authorization: Basic %s\n", str);
       g_free (str);
       if (ret < 0)
-	return (ret);
-    }
-
-  if (extrahdr)
-    {
-      request->logging_function (gftp_logging_send, request->user_data, "%s",
-                                 extrahdr);
-      if ((ret = gftp_write (request, extrahdr, strlen (extrahdr), 
-                             request->sockfd)) < 0)
         return (ret);
     }
 
-  if ((ret = gftp_write (request, "\n", 1, request->sockfd)) < 0)
+  if ((ret = request->write_function (request, "\n", 1, request->sockfd)) < 0)
     return (ret);
 
   return (rfc2068_read_response (request));
@@ -240,16 +207,14 @@
   gftp_lookup_request_option (request, "http_proxy_host", &proxy_hostname);
   gftp_lookup_request_option (request, "http_proxy_port", &proxy_port);
 
-  if (request->url_prefix != NULL)
-    g_free (request->url_prefix);
+  if (proxy_config != NULL && strcmp (proxy_config, "ftp") == 0)
+    {
+      g_free (request->url_prefix);
+      request->url_prefix = g_strdup ("ftp");
+    }
 
-  if (proxy_config != NULL && strcmp (proxy_config, "ftp") == 0)
-    request->url_prefix = g_strdup ("ftp");
-  else
-    request->url_prefix = g_strdup ("http");
-
-  if ((request->sockfd = gftp_connect_server (request, request->url_prefix, 
-                                              proxy_hostname, proxy_port)) < 0)
+  if (gftp_connect_server (request, request->url_prefix, proxy_hostname, 
+                           proxy_port) < 0)
     return (GFTP_ERETRYABLE);
 
   if (request->directory && *request->directory == '\0')
@@ -291,8 +256,8 @@
 rfc2068_get_file (gftp_request * request, const char *filename, int fd,
                   off_t startsize)
 {
-  char *tempstr, *extrahdr, *pos;
   int restarted, ret, use_http11;
+  char *tempstr, *oldstr, *pos;
   rfc2068_params * params;
   off_t size;
 
@@ -324,27 +289,29 @@
   else
     remove_double_slashes (tempstr);
 
-  if (!use_http11 || startsize == 0)
-    extrahdr = NULL;
-  else
+  if (use_http11 && startsize > 0)
     {
 #if defined (_LARGEFILE_SOURCE)
-      extrahdr = g_strdup_printf ("Range: bytes=%lld-\n", startsize);
       request->logging_function (gftp_logging_misc, request->user_data,
                               _("Starting the file transfer at offset %lld\n"),
                               startsize);
+
+      oldstr = tempstr;
+      tempstr = g_strdup_printf ("%sRange: bytes=%lld-\n", tempstr, startsize);
+      g_free (oldstr);
 #else
-      extrahdr = g_strdup_printf ("Range: bytes=%ld-\n", startsize);
       request->logging_function (gftp_logging_misc, request->user_data,
 			       _("Starting the file transfer at offset %ld\n"), 
                                startsize);
+
+      oldstr = tempstr;
+      tempstr = g_strdup_printf ("%sRange: bytes=%ld-\n", tempstr, startsize);
+      g_free (oldstr);
 #endif
     }
 
-  size = rfc2068_send_command (request, tempstr, extrahdr);
+  size = rfc2068_send_command (request, tempstr, strlen (tempstr));
   g_free (tempstr);
-  if (extrahdr)
-    g_free (extrahdr);
   if (size < 0)
     return (size);
 
@@ -360,6 +327,8 @@
       return (GFTP_ERETRYABLE);
     }
 
+  params->read_bytes = 0;
+
   return (restarted ? size + startsize : size);
 }
 
@@ -374,14 +343,8 @@
   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL);
 
   params = request->protocol_data;
-  if (params->max_bytes == params->read_bytes)
-    return (0);
 
-  if (params->max_bytes > 0 && 
-      size + params->read_bytes > params->max_bytes)
-    size = params->max_bytes - params->read_bytes;
-
-  if ((len = gftp_read (request, buf, size, request->sockfd)) < 0)
+  if ((len = request->read_function (request, buf, size, request->sockfd)) < 0)
     return ((ssize_t) len);
 
   return (len);
@@ -406,7 +369,9 @@
   request->sockfd = -1;
 
   params = request->protocol_data;
-  params->max_bytes = 0;
+  params->content_length = 0;
+  params->chunked_transfer = 0;
+  params->chunk_size = 0;
 
   request->logging_function (gftp_logging_misc, request->user_data,
                              _("Finished retrieving data\n"));
@@ -446,7 +411,7 @@
   else
     remove_double_slashes (tempstr);
 
-  ret = rfc2068_send_command (request, tempstr, NULL);
+  ret = rfc2068_send_command (request, tempstr, strlen (tempstr));
   g_free (tempstr);
   if (ret < 0)
     return ((int) ret);
@@ -459,7 +424,7 @@
                                  _("Retrieving directory listing...\n"));
       return (0);
     }
-  
+
   return (GFTP_ERETRYABLE);
 }
 
@@ -496,7 +461,7 @@
   else
     remove_double_slashes (tempstr);
 
-  size = rfc2068_send_command (request, tempstr, NULL);
+  size = rfc2068_send_command (request, tempstr, strlen (tempstr));
   g_free (tempstr);
   return (size);
 }
@@ -584,6 +549,9 @@
 
   fle->datetime = parse_time (pos, &pos);
 
+  fle->user = g_strdup (_("<unknown>"));
+  fle->group = g_strdup (_("<unknown>"));
+
   if (pos == NULL)
     return (1);
 
@@ -613,21 +581,22 @@
       if ((*stpos == '.') && isdigit (*(stpos + 1)) ) 
         {  /* found decimal point */
           fle->size = units * strtol (stpos + 1, NULL, 10);
-          fle->size /= 10;
+          fle->size /= 10; /* FIXME */
         }
     }
 
   fle->size += units * strtol (stpos, NULL, 10);
+
   return (1);
 }
 
 
-static int
+int
 rfc2068_get_next_file (gftp_request * request, gftp_file * fle, int fd)
 {
   rfc2068_params * params;
   char tempstr[255];
-  size_t len;
+  ssize_t len;
   int ret;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
@@ -646,35 +615,13 @@
 
   while (1)
     {
-      if ((ret = gftp_get_line (request, &params->rbuf, tempstr, sizeof (tempstr), 
-                                fd)) < 0)
+      if ((ret = gftp_get_line (request, &params->rbuf, tempstr, sizeof (tempstr), fd)) <= 0)
         return (ret);
 
-      params->read_bytes += strlen (tempstr);
-
-      if (params->chunked_transfer && strcmp (tempstr, "0") == 0)
-        {
-          while ((len = gftp_get_line (request, &params->rbuf, tempstr, 
-                                       sizeof (tempstr), fd)) > 0)
-            {
-              if (*tempstr == '\0')
-                break;
-            }
-	  gftp_file_destroy (fle);
-
-          if (len < 0)
-            return (len);
-
-          return (0);
-        }
-
       if (parse_html_line (tempstr, fle) == 0 || fle->file == NULL)
 	gftp_file_destroy (fle);
       else
 	break;
-
-      if (params->max_bytes != 0 && params->read_bytes == params->max_bytes)
-	break;
     }
 
   if (fle->file == NULL)
@@ -727,6 +674,91 @@
 }
 
 
+static ssize_t 
+rfc2068_chunked_read (gftp_request * request, void *ptr, size_t size, int fd)
+{
+  rfc2068_params * params;
+  char *stpos, *endpos;
+  size_t read_size;
+  ssize_t retval;
+
+  params = request->protocol_data;
+
+  read_size = size;
+  if (params->content_length > 0)
+    {
+      if (params->content_length == params->read_bytes)
+        return (0);
+
+      if (read_size + params->read_bytes > params->content_length)
+        read_size = params->content_length - params->read_bytes;
+    }
+  else if (params->chunked_transfer && params->chunk_size > 0 &&
+           params->chunk_size < read_size)
+    read_size = params->chunk_size;
+
+  retval = params->real_read_function (request, ptr, read_size, fd);
+
+  if (retval > 0)
+    params->read_bytes += retval;
+
+  if (!params->chunked_transfer || retval <= 0)
+    return (retval);
+
+  if (params->chunk_size == 0)
+    {
+      stpos = (char *) ptr;
+
+      while (params->chunk_size == 0)
+        {
+          if (*stpos != '\r' || *(stpos + 1) != '\n')
+            {
+              request->logging_function (gftp_logging_recv, request->user_data,
+                                         _("Received wrong response from server, disconnecting\n"));
+              gftp_disconnect (request);
+              return (GFTP_EFATAL);
+            }
+
+          for (endpos = stpos + 2; 
+               *endpos != '\n'; 
+               endpos++);
+    
+          /* FIXME extra checks */
+
+          *endpos = '\0';
+          if (*(endpos - 1) == '\r')
+            *(endpos - 1) = '\0';
+    
+          if (sscanf (stpos + 2, "%lx", &params->chunk_size) != 1)
+            {
+              request->logging_function (gftp_logging_recv, request->user_data,
+                                         _("Received wrong response from server, disconnecting\n"));
+              gftp_disconnect (request);
+              return (GFTP_EFATAL);
+            }
+    
+          if (params->chunk_size == 0)
+            return (0);
+    
+          retval -= endpos - (char *) ptr + 1;
+          params->chunk_size -= retval;
+          memmove (stpos, endpos + 1, retval);
+          ((char *) stpos)[retval] = '\0';
+
+          if (params->chunk_size == 0)
+            {
+              stpos += params->chunk_size;
+              continue;
+            }
+        }
+    }
+  else if (retval > 0)
+    params->chunk_size -= retval;
+
+  return (retval);
+}
+
+
 void 
 rfc2068_register_module (void)
 {
@@ -737,12 +769,17 @@
 void
 rfc2068_init (gftp_request * request)
 {
+  rfc2068_params * params;
+
   g_return_if_fail (request != NULL);
 
   request->protonum = GFTP_HTTP_NUM;
   request->init = rfc2068_init;
+  request->read_function = rfc2068_chunked_read;
+  request->write_function = gftp_fd_write;
   request->destroy = rfc2068_destroy;
   request->connect = rfc2068_connect;
+  request->post_connect = NULL;
   request->disconnect = rfc2068_disconnect;
   request->get_file = rfc2068_get_file;
   request->put_file = NULL;
@@ -770,7 +807,11 @@
   request->use_cache = 1;
   request->use_threads = 1;
   request->always_connected = 1;
+
   request->protocol_data = g_malloc0 (sizeof (rfc2068_params));
+  params = request->protocol_data;
+  params->real_read_function = gftp_fd_read;
+
   gftp_set_config_options (request);
 }
 
--- a/lib/rfc959.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/rfc959.c	Sun Jun 08 15:04:40 2003 +0000
@@ -165,7 +165,7 @@
                                  command);
     }
 
-  if ((ret = gftp_write (request, command, strlen (command), 
+  if ((ret = gftp_fd_write (request, command, strlen (command), 
                          request->sockfd)) < 0)
     return (ret);
 
@@ -435,8 +435,7 @@
   else if (strcasecmp (request->username, "anonymous") == 0)
     gftp_set_password (request, email);
    
-  if ((request->sockfd = gftp_connect_server (request, "ftp", proxy_hostname,
-                                              proxy_port)) < 0)
+  if (gftp_connect_server (request, "ftp", proxy_hostname, proxy_port) < 0)
     return (request->sockfd);
 
   /* Get the banner */
@@ -879,7 +878,7 @@
 
   cli_addr_len = sizeof (cli_addr);
 
-  if ((ret = gftp_set_sockblocking (request, request->datafd, 0)) < 0)
+  if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 0)) < 0)
     return (ret);
 
   if ((infd = accept (request->datafd, (struct sockaddr *) &cli_addr,
@@ -895,7 +894,7 @@
   close (request->datafd);
 
   request->datafd = infd;
-  if ((ret = gftp_set_sockblocking (request, request->datafd, 1)) < 0)
+  if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 1)) < 0)
     return (ret);
 
   return (0);
@@ -985,7 +984,7 @@
       (ret = rfc959_data_connection_new (request)) < 0)
     return (ret);
 
-  if ((ret = gftp_set_sockblocking (request, request->datafd, 1)) < 0)
+  if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 1)) < 0)
     return (ret);
 
   if (startsize > 0)
@@ -1056,7 +1055,7 @@
       (ret = rfc959_data_connection_new (request)) < 0)
     return (ret);
 
-  if ((ret = gftp_set_sockblocking (request, request->datafd, 1)) < 0)
+  if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 1)) < 0)
     return (ret);
 
   if (startsize > 0)
@@ -1137,7 +1136,7 @@
   g_free (tempstr);
 
   tempstr = g_strconcat ("RETR ", fromfile, "\r\n", NULL);
-  if ((ret = gftp_write (fromreq, tempstr, strlen (tempstr), 
+  if ((ret = gftp_fd_write (fromreq, tempstr, strlen (tempstr), 
                          fromreq->sockfd)) < 0)
     {
       g_free (tempstr);
@@ -1146,7 +1145,8 @@
   g_free (tempstr);
 
   tempstr = g_strconcat ("STOR ", tofile, "\r\n", NULL);
-  if ((ret = gftp_write (toreq, tempstr, strlen (tempstr), toreq->sockfd)) < 0)
+  if ((ret = gftp_fd_write (toreq, tempstr, strlen (tempstr), 
+                            toreq->sockfd)) < 0)
     {
       g_free (tempstr);
       return (ret);
@@ -1262,7 +1262,7 @@
   int i, j, ascii_transfers;
   ssize_t num_read;
 
-  num_read = gftp_read (request, buf, size, request->datafd);
+  num_read = gftp_fd_read (request, buf, size, request->datafd);
   if (num_read < 0)
     return (num_read);
 
@@ -1324,7 +1324,7 @@
       tempstr = buf;
     }
 
-  num_wrote = gftp_write (request, tempstr, rsize, request->datafd);
+  num_wrote = gftp_fd_write (request, tempstr, rsize, request->datafd);
 
   if (tempstr != buf)
     g_free (tempstr);
@@ -1381,7 +1381,7 @@
   if (!request->cached)
     {
       request->last_dir_entry = g_strdup_printf ("%s\n", tempstr);
-      request->last_dir_entry_len = len + 1;
+      request->last_dir_entry_len = strlen (tempstr) + 1;
     }
   return (len);
 }
@@ -1609,7 +1609,10 @@
   request->protonum = GFTP_FTP_NUM;
   request->init = rfc959_init;
   request->destroy = NULL; 
+  request->read_function = gftp_fd_read;
+  request->write_function = gftp_fd_write;
   request->connect = rfc959_connect;
+  request->post_connect = NULL;
   request->disconnect = rfc959_disconnect;
   request->get_file = rfc959_get_file;
   request->put_file = rfc959_put_file;
--- a/lib/sshv2.c	Wed May 28 18:37:28 2003 +0000
+++ b/lib/sshv2.c	Sun Jun 08 15:04:40 2003 +0000
@@ -269,7 +269,7 @@
   wrotepw = 0;
   ok = 1;
 
-  if (gftp_set_sockblocking (request, fd, 1) == -1)
+  if (gftp_fd_set_sockblocking (request, fd, 1) == -1)
     return (NULL);
 
   pwstr = g_strconcat (request->password, "\n", NULL);
@@ -277,7 +277,7 @@
   errno = 0;
   while (1)
     {
-      if ((rd = gftp_read (request, tempstr + diff, rem - 1, fd)) <= 0)
+      if ((rd = gftp_fd_read (request, tempstr + diff, rem - 1, fd)) <= 0)
         {
           ok = 0;
           break;
@@ -302,7 +302,7 @@
             }
               
           wrotepw = 1;
-          if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0)
+          if (gftp_fd_write (request, pwstr, strlen (pwstr), fd) < 0)
             {
               ok = 0;
               break;
@@ -327,7 +327,7 @@
             }
 
           wrotepw = 1;
-          if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0)
+          if (gftp_fd_write (request, pwstr, strlen (pwstr), fd) < 0)
             {
               ok = 0;
               break;
@@ -585,7 +585,7 @@
 
   sshv2_log_command (request, gftp_logging_send, type, buf + 5, len);
 
-  if ((ret = gftp_write (request, buf, len + 5, request->sockfd)) < 0)
+  if ((ret = gftp_fd_write (request, buf, len + 5, request->sockfd)) < 0)
     return (ret);
 
   return (0);
@@ -606,7 +606,7 @@
   rem = 5;
   while (rem > 0)
     {
-      if ((numread = gftp_read (request, pos, rem, fd)) < 0)
+      if ((numread = gftp_fd_read (request, pos, rem, fd)) < 0)
         return ((int) numread);
       rem -= numread;
       pos += numread;
@@ -634,7 +634,7 @@
   rem = message->length - 1;
   while (rem > 0)
     {
-      if ((numread = gftp_read (request, pos, rem, fd)) < 0)
+      if ((numread = gftp_fd_read (request, pos, rem, fd)) < 0)
         return ((int) numread);
       rem -= numread;
       pos += numread;
@@ -2255,7 +2255,10 @@
   request->protonum = GFTP_SSHV2_NUM;
   request->init = sshv2_init;
   request->destroy = sshv2_destroy;
+  request->read_function = gftp_fd_read;
+  request->write_function = gftp_fd_write;
   request->connect = sshv2_connect;
+  request->post_connect = NULL;
   request->disconnect = sshv2_disconnect;
   request->get_file = sshv2_get_file;
   request->put_file = sshv2_put_file;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/sslcommon.c	Sun Jun 08 15:04:40 2003 +0000
@@ -0,0 +1,345 @@
+/*****************************************************************************/
+/*  sslcommon.c - interface to OpenSSL                                       */
+/*  Copyright (C) 1998-2003 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$";
+
+/* Some of the functions in here was taken either entirely or partially from
+ * the O'Reilly book Network Security with OpenSSL */
+
+static SSL_CTX * ctx = NULL;
+ 
+#ifdef USE_SSL
+
+static volatile int gftp_ssl_initialized = 0;
+
+static int 
+gftp_ssl_verify_callback (int ok, X509_STORE_CTX *store)
+{
+  char data[256];
+
+  if (!ok)
+    {
+      X509 *cert = X509_STORE_CTX_get_current_cert (store);
+      int depth = X509_STORE_CTX_get_error_depth (store);
+      int err = X509_STORE_CTX_get_error (store);
+
+      fprintf (stderr, "-Error with certificate at depth: %i\n", depth);
+      X509_NAME_oneline (X509_get_issuer_name (cert), data, sizeof (data));
+      fprintf (stderr, "  issuer   = %s\n", data);
+      X509_NAME_oneline (X509_get_subject_name (cert), data, sizeof (data));
+      fprintf (stderr, "  subject  = %s\n", data);
+      fprintf (stderr, "  err %i:%s\n", err, X509_verify_cert_error_string (err));
+    }
+
+  return ok;
+}
+
+
+static int
+gftp_ssl_post_connection_check (gftp_request * request)
+{
+  char data[256], *extstr;
+  int extcount, ok, i, j;
+  X509_EXTENSION *ext;
+  X509_NAME *subj;
+  X509 *cert;
+ 
+  ok = 0;
+  if (!(cert = SSL_get_peer_certificate (request->ssl)))
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Cannot get peer certificate\n"));
+      return (X509_V_ERR_APPLICATION_VERIFICATION);
+    }
+         
+  if ((extcount = X509_get_ext_count (cert)) > 0)
+    {
+      for (i = 0; i < extcount; i++)
+        {
+          ext = X509_get_ext (cert, i);
+          extstr = (char *) OBJ_nid2sn (OBJ_obj2nid (X509_EXTENSION_get_object (ext)));
+ 
+          if (strcmp (extstr, "subjectAltName") == 0)
+            {
+    unsigned char  *data;
+    STACK_OF(CONF_VALUE) *val;
+    CONF_VALUE   *nval;
+    X509V3_EXT_METHOD *meth;
+    void     *ext_str = NULL;
+ 
+    if (!(meth = X509V3_EXT_get(ext)))
+     break;
+    data = ext->value->data;
+
+#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
+    if (meth->it)
+     ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
+           ASN1_ITEM_ptr(meth->it));
+    else
+     ext_str = meth->d2i(NULL, &data, ext->value->length);
+#else
+    ext_str = meth->d2i(NULL, &data, ext->value->length);
+#endif
+    val = meth->i2v(meth, ext_str, NULL);
+    for (j = 0; j < sk_CONF_VALUE_num(val); j++)
+    {
+     nval = sk_CONF_VALUE_value(val, j);
+     if (strcmp(nval->name, "DNS") == 0 && strcmp(nval->value, request->hostname) == 0)
+     {
+      ok = 1;
+      break;
+     }
+    }
+   }
+   if (ok)
+    break;
+  }
+ }
+ 
+/* FIXME
+ if (!ok && (subj = X509_get_subject_name (cert)) &&
+     X509_NAME_get_text_by_NID (subj, NID_commonName, data, 256) > 0)
+   {
+     data[sizeof (data) - 1] = '\0';
+     if (strcasecmp (data, request->hostname) != 0)
+       {
+         request->logging_function (gftp_logging_error, request->user_data,
+                                    _("The SSL certificate's host %s does not match the host %s that we connected to\n"),
+                                    data, request->hostname);
+         X509_free (cert);
+         return (X509_V_ERR_APPLICATION_VERIFICATION);
+       }
+   }
+*/
+ 
+  X509_free (cert);
+  return (SSL_get_verify_result(request->ssl));
+}
+
+
+int
+gftp_ssl_startup (gftp_request * request)
+{
+  gftp_ssl_initialized = 1;
+
+  /* FIXME _ thread setup */
+  /* FIXME - only call this from one place */
+  if (!SSL_library_init ())
+    {
+      if (request != NULL)
+        request->logging_function (gftp_logging_error, request->user_data,
+                                   _("Cannot initialized the OpenSSL library\n"));
+      return (GFTP_EFATAL);
+    }
+
+  SSL_load_error_strings (); 
+  RAND_load_file ("/dev/urandom", 1024); /* FIXME - be able to specify this file */
+
+  ctx = SSL_CTX_new (SSLv23_method ());
+
+  if (SSL_CTX_set_default_verify_paths (ctx) != 1)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error loading default SSL certificates\n"));
+       return (GFTP_EFATAL);
+    }
+
+  SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, gftp_ssl_verify_callback);
+  SSL_CTX_set_verify_depth (ctx, 4);
+  SSL_CTX_set_options (ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
+
+  if (SSL_CTX_set_cipher_list (ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error setting cipher list (no valid ciphers)\n"));
+      return (GFTP_EFATAL);
+    }
+
+
+  return (0);
+}
+
+
+int
+gftp_ssl_session_setup (gftp_request * request)
+{
+  BIO * bio;
+  long ret;
+
+  g_return_val_if_fail (request->sockfd > 0, GFTP_EFATAL);
+
+  if (!gftp_ssl_initialized)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error: SSL engine was not initialized\n"));
+      return (GFTP_EFATAL);
+    }
+
+  if (gftp_fd_set_sockblocking (request, request->sockfd, 0) < 0) /* FIXME */
+    {
+      gftp_disconnect (request);
+      return (GFTP_ERETRYABLE);
+    }
+
+  if ((bio = BIO_new (BIO_s_socket ())) == NULL)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error setting up SSL connection (BIO object)\n"));
+      return (GFTP_EFATAL);
+    }
+
+  BIO_set_fd (bio, request->sockfd, BIO_NOCLOSE);
+
+  if ((request->ssl = SSL_new (ctx)) == NULL)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error setting up SSL connection (SSL object)\n"));
+      return (GFTP_EFATAL);
+    }
+
+  SSL_set_bio (request->ssl, bio, bio);
+
+  if (SSL_connect (request->ssl) <= 0)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error connecting to SSL object\n"));
+      return (GFTP_EFATAL);
+    }
+
+  if ((ret = gftp_ssl_post_connection_check (request)) != X509_V_OK)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error with peer certificate: %s\n"),
+                                 X509_verify_cert_error_string (ret));
+      return (GFTP_EFATAL);
+    }
+
+  request->logging_function (gftp_logging_misc, request->user_data,
+                             "SSL connection established using %s (%s)\n", 
+                             SSL_get_cipher_version (request->ssl), 
+                             SSL_get_cipher_name (request->ssl));
+
+  return (0);
+}
+
+
+ssize_t 
+gftp_ssl_read (gftp_request * request, void *ptr, size_t size, int fd)
+{
+  ssize_t ret;
+  int err;
+
+  if (!gftp_ssl_initialized)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error: SSL engine was not initialized\n"));
+      return (GFTP_EFATAL);
+    }
+
+  errno = 0;
+  ret = 0;
+  do
+    {
+      if ((ret = SSL_read (request->ssl, ptr, size)) < 0)
+        { 
+          err = SSL_get_error (request->ssl, ret);
+           printf ("error is %d\n", err);
+          if (errno == EINTR)
+            {
+              if (request != NULL && request->cancel)
+                break;
+              else
+                continue;
+             }
+ 
+          if (request != NULL)
+            {
+              request->logging_function (gftp_logging_error, request->user_data,
+                                   _("Error: Could not read from socket: %s\n"),
+                                    g_strerror (errno));
+              gftp_disconnect (request);
+            }
+          return (GFTP_ERETRYABLE);
+        }
+    }
+  while (errno == EINTR && !(request != NULL && request->cancel));
+
+  if (errno == EINTR && request != NULL && request->cancel)
+    {
+      gftp_disconnect (request);
+      return (GFTP_ERETRYABLE);
+    }
+
+  return (ret);
+}
+
+
+ssize_t 
+gftp_ssl_write (gftp_request * request, const char *ptr, size_t size, int fd)
+{
+  size_t ret, w_ret;
+ 
+  if (!gftp_ssl_initialized)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Error: SSL engine was not initialized\n"));
+      return (GFTP_EFATAL);
+    }
+
+  ret = 0;
+  do
+    {
+      w_ret = SSL_write (request->ssl, ptr, size);
+      if (w_ret <= 0)
+        {
+          if (errno == EINTR)
+            {
+              if (request != NULL && request->cancel)
+                break;
+              else
+                continue;
+             }
+ 
+          if (request != NULL)
+            {
+              request->logging_function (gftp_logging_error, request->user_data,
+                                    _("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);
+
+  if (errno == EINTR && request != NULL && request->cancel)
+    {
+      gftp_disconnect (request);
+      return (GFTP_ERETRYABLE);
+    }
+
+  return (ret);
+}
+
+#endif
--- a/src/gtk/bookmarks.c	Wed May 28 18:37:28 2003 +0000
+++ b/src/gtk/bookmarks.c	Sun Jun 08 15:04:40 2003 +0000
@@ -879,7 +879,7 @@
     {
       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (dialog->window, gftp_version);
     }
 
   tempwid = gtk_frame_new (NULL);
@@ -1259,7 +1259,7 @@
     {
       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (dialog->window, gftp_version);
     }
 
   /* FIXME - memory leak */
--- a/src/gtk/chmod_dialog.c	Wed May 28 18:37:28 2003 +0000
+++ b/src/gtk/chmod_dialog.c	Sun Jun 08 15:04:40 2003 +0000
@@ -183,7 +183,7 @@
     {
       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (dialog->window, gftp_version);
     }
 
   tempwid = gtk_label_new (_("You can now adjust the attributes of your file(s)\nNote: Not all ftp servers support the chmod feature"));
--- a/src/gtk/gftp-gtk.c	Wed May 28 18:37:28 2003 +0000
+++ b/src/gtk/gftp-gtk.c	Sun Jun 08 15:04:40 2003 +0000
@@ -1096,7 +1096,7 @@
     {
       gdk_window_set_icon (window->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (window->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (window->window, gftp_version);
     }
 
   other_wdata = &window1;
--- a/src/gtk/menu-items.c	Wed May 28 18:37:28 2003 +0000
+++ b/src/gtk/menu-items.c	Sun Jun 08 15:04:40 2003 +0000
@@ -756,7 +756,7 @@
     {
       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (dialog->window, gftp_version);
     }
 
   notebook = gtk_notebook_new ();
--- a/src/gtk/misc-gtk.c	Wed May 28 18:37:28 2003 +0000
+++ b/src/gtk/misc-gtk.c	Sun Jun 08 15:04:40 2003 +0000
@@ -523,9 +523,9 @@
 }
 
 
+/* FIXME - check this */
 static gchar *
-gftp_item_factory_translate (const char *path,
-			     gpointer    func_data)
+gftp_item_factory_translate (const char *path, gpointer func_data)
 {
   const gchar *strip_prefix = func_data;
   const char *result;
@@ -535,7 +535,7 @@
       char *tmp_path = g_strconcat (strip_prefix, path, NULL);
       result = gettext (tmp_path);
       if (result == tmp_path)
-	result = path;
+        result = path;
       g_free (tmp_path);
     }
   else
@@ -946,7 +946,7 @@
     {
       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (dialog->window, gftp_version);
     }
 
   ddata->dialog = dialog;
@@ -1070,7 +1070,7 @@
     {
       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (dialog->window, gftp_version);
     }
 
   ddata->dialog = dialog;
--- a/src/gtk/options_dialog.c	Wed May 28 18:37:28 2003 +0000
+++ b/src/gtk/options_dialog.c	Sun Jun 08 15:04:40 2003 +0000
@@ -1203,7 +1203,7 @@
     {
       gdk_window_set_icon (option_data.dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (option_data.dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (option_data.dialog->window, gftp_version);
     }
 
   option_data.notebook = gtk_notebook_new ();
--- a/src/gtk/view_dialog.c	Wed May 28 18:37:28 2003 +0000
+++ b/src/gtk/view_dialog.c	Sun Jun 08 15:04:40 2003 +0000
@@ -327,7 +327,7 @@
     {
       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
                            gftp_icon->bitmap);
-      gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
+      gdk_window_set_icon_name (dialog->window, gftp_version);
     }
 
   table = gtk_table_new (1, 2, FALSE);