Index: lib/easy.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/easy.c,v
retrieving revision 1.108
diff -u -r1.108 easy.c
--- lib/easy.c	26 Aug 2007 05:53:26 -0000	1.108
+++ lib/easy.c	12 Oct 2007 22:26:23 -0000
@@ -681,6 +681,7 @@
 
   Curl_safefree(data->reqdata.proto.generic);
   data->reqdata.proto.generic=NULL;
+  data->reqdata.proto_disconnect = NULL;
 
   /* zero out UserDefined data: */
   Curl_freeset(data);
Index: lib/file.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/file.c,v
retrieving revision 1.94
diff -u -r1.94 file.c
--- lib/file.c	12 Oct 2007 13:36:38 -0000	1.94
+++ lib/file.c	12 Oct 2007 22:26:23 -0000
@@ -123,8 +123,8 @@
  */
 CURLcode Curl_file_connect(struct connectdata *conn)
 {
-  char *real_path = curl_easy_unescape(conn->data, conn->data->reqdata.path, 0,
-                                       NULL);
+  struct SessionHandle *data = conn->data;
+  char *real_path = curl_easy_unescape(data, data->reqdata.path, 0, NULL);
   struct FILEPROTO *file;
   int fd;
 #if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
@@ -135,16 +135,17 @@
   if(!real_path)
     return CURLE_OUT_OF_MEMORY;
 
+  /* If there already is a protocol-specific struct allocated for this
+     sessionhandle, deal with it */
+  Curl_reset_reqproto(conn);
+
   file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1);
   if(!file) {
     free(real_path);
     return CURLE_OUT_OF_MEMORY;
   }
 
-  if (conn->data->reqdata.proto.file)
-    free(conn->data->reqdata.proto.file);
-
-  conn->data->reqdata.proto.file = file;
+  data->reqdata.proto.file = file;
 
 #if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
   /* If the first character is a slash, and there's
@@ -184,8 +185,8 @@
   file->freepath = real_path; /* free this when done */
 
   file->fd = fd;
-  if(!conn->data->set.upload && (fd == -1)) {
-    failf(conn->data, "Couldn't open file %s", conn->data->reqdata.path);
+  if(!data->set.upload && (fd == -1)) {
+    failf(data, "Couldn't open file %s", data->reqdata.path);
     Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
     return CURLE_FILE_COULDNT_READ_FILE;
   }
Index: lib/ftp.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ftp.c,v
retrieving revision 1.445
diff -u -r1.445 ftp.c
--- lib/ftp.c	12 Oct 2007 18:49:14 -0000	1.445
+++ lib/ftp.c	12 Oct 2007 22:26:24 -0000
@@ -90,6 +90,7 @@
 #include "parsedate.h" /* for the week day and month names */
 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
 #include "multiif.h"
+#include "url.h"
 
 #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
 #include "inet_ntoa_r.h"
@@ -3010,6 +3011,7 @@
     return CURLE_OUT_OF_MEMORY;
 
   data->reqdata.proto.ftp = ftp;
+  data->reqdata.proto_disconnect = Curl_ftp_disconnect;
 
   /* get some initial data into the ftp struct */
   ftp->bytecountp = &data->reqdata.keep.bytecount;
@@ -3045,11 +3047,9 @@
 
   *done = FALSE; /* default to not done yet */
 
-  if (data->reqdata.proto.ftp) {
-    Curl_ftp_disconnect(conn);
-    free(data->reqdata.proto.ftp);
-    data->reqdata.proto.ftp = NULL;
-  }
+  /* If there already is a protocol-specific struct allocated for this
+     sessionhandle, deal with it */
+  Curl_reset_reqproto(conn);
 
   result = ftp_init(conn);
   if(result)
Index: lib/http.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/http.c,v
retrieving revision 1.340
diff -u -r1.340 http.c
--- lib/http.c	12 Oct 2007 18:49:14 -0000	1.340
+++ lib/http.c	12 Oct 2007 22:26:25 -0000
@@ -1894,17 +1894,15 @@
      the rest of the request in the PERFORM phase. */
   *done = TRUE;
 
-  if(!data->reqdata.proto.http) {
-    /* Only allocate this struct if we don't already have it! */
-
-    http = (struct HTTP *)malloc(sizeof(struct HTTP));
-    if(!http)
-      return CURLE_OUT_OF_MEMORY;
-    memset(http, 0, sizeof(struct HTTP));
-    data->reqdata.proto.http = http;
-  }
-  else
-    http = data->reqdata.proto.http;
+  /* If there already is a protocol-specific struct allocated for this
+     sessionhandle, deal with it */
+  Curl_reset_reqproto(conn);
+
+  http = (struct HTTP *)malloc(sizeof(struct HTTP));
+  if(!http)
+    return CURLE_OUT_OF_MEMORY;
+  memset(http, 0, sizeof(struct HTTP));
+  data->reqdata.proto.http = http;
 
   if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
        data->set.upload) {
Index: lib/ssh.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ssh.c,v
retrieving revision 1.78
diff -u -r1.78 ssh.c
--- lib/ssh.c	12 Oct 2007 13:36:38 -0000	1.78
+++ lib/ssh.c	12 Oct 2007 22:26:27 -0000
@@ -1846,10 +1846,9 @@
   CURLcode result;
   struct SessionHandle *data = conn->data;
 
-  if (data->reqdata.proto.ssh) {
-    Curl_safefree(data->reqdata.proto.ssh);
-    data->reqdata.proto.ssh = NULL;
-  }
+  /* If there already is a protocol-specific struct allocated for this
+     sessionhandle, deal with it */
+  Curl_reset_reqproto(conn);
 
   result = ssh_init(conn);
   if (result)
Index: lib/url.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.c,v
retrieving revision 1.654
diff -u -r1.654 url.c
--- lib/url.c	12 Oct 2007 20:53:43 -0000	1.654
+++ lib/url.c	12 Oct 2007 22:26:27 -0000
@@ -4445,3 +4445,18 @@
 
   return result;
 }
+
+/* Called on connect, and if there's already a protocol-specific struct
+   allocated this "deals with that" (possibly closes stuff and frees it) so
+   that it can be setup properly later on. */
+void Curl_reset_reqproto(struct connectdata *conn)
+{
+  struct SessionHandle *data = conn->data;
+  if (data->reqdata.proto.generic) {
+    if(data->reqdata.proto_disconnect)
+      data->reqdata.proto_disconnect(conn);
+    free(data->reqdata.proto.generic);
+    data->reqdata.proto.generic = NULL;
+    data->reqdata.proto_disconnect = NULL;
+  }
+}
Index: lib/url.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.h,v
retrieving revision 1.35
diff -u -r1.35 url.h
--- lib/url.h	27 Sep 2007 01:45:23 -0000	1.35
+++ lib/url.h	12 Oct 2007 22:26:27 -0000
@@ -84,4 +84,9 @@
                           int *max_fdp);
 #endif
 
+/* Called on connect, and if there's already a protocol-specific struct
+   allocated this "deals with that" (possibly closes stuff and frees it) so
+   that it can be setup properly later on. */
+void Curl_reset_reqproto(struct connectdata *conn);
+
 #endif
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.351
diff -u -r1.351 urldata.h
--- lib/urldata.h	12 Oct 2007 13:36:38 -0000	1.351
+++ lib/urldata.h	12 Oct 2007 22:26:28 -0000
@@ -807,6 +807,14 @@
     void *generic;
     struct SSHPROTO *ssh;
   } proto;
+
+  /* The proto_disconnect function is ran if the proto previously used needs
+     to be disconnected. Like when Curl_ftp_connect() is called and it finds
+     that there's already a proto allocated, that proto is first disconnected
+     - with this function. Then re-initialized.
+   */
+  CURLcode (*proto_disconnect)(struct connectdata *);
+
 };
 
 /*
