--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\file.c	2006-05-05 04:00:54.001 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\file.c	2006-08-09 23:19:16.000 +0200
@@ -311,11 +311,11 @@
     CURLcode result;
     snprintf(buf, sizeof(data->state.buffer),
              "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size);
-    result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
+    result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
     if(result)
       return result;
 
-    result = Curl_client_write(data, CLIENTWRITE_BOTH,
+    result = Curl_client_write(conn, CLIENTWRITE_BOTH,
                                (char *)"Accept-ranges: bytes\r\n", 0);
     if(result)
       return result;
@@ -339,7 +339,7 @@
                tm->tm_hour,
                tm->tm_min,
                tm->tm_sec);
-      result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
+      result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
     }
     return result;
   }
@@ -377,7 +377,7 @@
 
     bytecount += nread;
 
-    res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
+    res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
     if(res)
       return res;
 

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\ftp.c	2006-07-26 04:00:42.000 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\ftp.c	2006-08-10 16:37:45.000 +0200
@@ -132,6 +132,10 @@
 static CURLcode ftp_state_post_cwd(struct connectdata *conn);
 static CURLcode ftp_state_quote(struct connectdata *conn,
                                 bool init, ftpstate instate);
+static CURLcode ftp_nbsendtransfertype(struct connectdata *conn,
+                                  bool ascii, ftpstate state);
+static int ftp_should_send_transfertype (struct connectdata *conn,
+                                  bool ascii);
 
 /* easy-to-use macro: */
 #define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result
@@ -339,7 +343,7 @@
            * for "headers". The response lines can be seen as a kind of
            * headers.
            */
-          result = Curl_client_write(data, CLIENTWRITE_HEADER,
+          result = Curl_client_write(conn, CLIENTWRITE_HEADER,
                                      ftp->linestart_resp, perline);
           if(result)
             return result;
@@ -570,7 +574,7 @@
              * for "headers". The response lines can be seen as a kind of
              * headers.
              */
-            result = Curl_client_write(data, CLIENTWRITE_HEADER,
+            result = Curl_client_write(conn, CLIENTWRITE_HEADER,
                                        line_start, perline);
             if(result)
               return result;
@@ -1206,11 +1210,15 @@
   struct SessionHandle *data = conn->data;
 
   if(ftp->no_transfer || conn->bits.no_body) {
-    /* then we're done with a "head"-like request, goto STOP */
-    state(conn, FTP_STOP);
 
     /* doesn't transfer any data */
     ftp->no_transfer = TRUE;
+
+    /* then we're done with a "head"-like request, goto STOP */
+	/* still do PRE QUOTE jobs, to let the opportunity to the user to
+       profit from the CWD infrastructure */
+    state(conn, FTP_RETR_PREQUOTE);
+	result = ftp_state_quote (conn, TRUE, FTP_RETR_PREQUOTE);
   }
   else if(data->set.ftp_use_port) {
     /* We have chosen to use the PORT (or similar) command */
@@ -1312,7 +1320,8 @@
   /* If we have selected NOBODY and HEADER, it means that we only want file
      information. Which in FTP can't be much more than the file size and
      date. */
-  if(conn->bits.no_body && data->set.include_header && ftp->file) {
+  if(conn->bits.no_body && data->set.include_header && ftp->file &&
+	  ftp_should_send_transfertype(conn, data->set.ftp_ascii)) {
     /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
        may not support it! It is however the only way we have to get a file's
        size! */
@@ -1321,11 +1330,7 @@
 
     /* Some servers return different sizes for different modes, and thus we
        must set the proper type before we check the size */
-    NBFTPSENDF(conn, "TYPE %c",
-               data->set.ftp_ascii?'A':'I');
-    state(conn, FTP_TYPE);
-    /* keep track of our current transfer type */
-    data->ftp_in_ascii_mode = data->set.ftp_ascii;
+    if ((result=ftp_nbsendtransfertype(conn, data->set.ftp_ascii, FTP_TYPE))) return result;
   }
   else
     result = ftp_state_post_type(conn);
@@ -1497,8 +1502,12 @@
       result = ftp_state_cwd(conn);
       break;
     case FTP_RETR_PREQUOTE:
-      NBFTPSENDF(conn, "SIZE %s", ftp->file);
-      state(conn, FTP_RETR_SIZE);
+      if (ftp->no_transfer)
+        state(conn, FTP_STOP);
+	  else {
+        NBFTPSENDF(conn, "SIZE %s", ftp->file);
+        state(conn, FTP_RETR_SIZE);
+      }
       break;
     case FTP_STOR_PREQUOTE:
       result = ftp_state_ul_setup(conn, FALSE);
@@ -1823,7 +1832,7 @@
                  tm->tm_hour,
                  tm->tm_min,
                  tm->tm_sec);
-        result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
+        result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
         if(result)
           return result;
       } /* end of a ridiculous amount of conditionals */
@@ -1998,7 +2007,7 @@
     if(-1 != filesize) {
       snprintf(buf, sizeof(data->state.buffer),
                "Content-Length: %" FORMAT_OFF_T "\r\n", filesize);
-      result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
+      result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
       if(result)
         return result;
     }
@@ -2025,7 +2034,7 @@
   case FTP_REST:
   default:
     if (ftpcode == 350) {
-      result = Curl_client_write(conn->data, CLIENTWRITE_BOTH,
+      result = Curl_client_write(conn, CLIENTWRITE_BOTH,
                                (char *)"Accept-ranges: bytes\r\n", 0);
       if(result)
         return result;
@@ -3090,7 +3099,7 @@
   ssize_t nread;
   CURLcode result;
 
-  FTPSENDF(conn, "TYPE %s", ascii?"A":"I");
+  FTPSENDF(conn, "TYPE %c", ascii?'A':'I');
 
   result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
   if(result)
@@ -3102,8 +3111,52 @@
     return ascii? CURLE_FTP_COULDNT_SET_ASCII:CURLE_FTP_COULDNT_SET_BINARY;
   }
   /* keep track of our current transfer type */
-  data->ftp_in_ascii_mode = ascii;
+  conn->proto.ftp->transfertype = ascii?'A':'I';
+
+  return CURLE_OK;
+}
+
 
+/***********************************************************************
+ *
+ * ftp_should_send_transfertype()
+ *
+ * returns true if in current situation, we would send transfer type
+ */
+static int ftp_should_send_transfertype (struct connectdata *conn,
+                                  bool ascii)
+{
+  struct SessionHandle *data = conn->data;
+  struct FTP *ftp = conn->proto.ftp;
+  return ftp->transfertype == (ascii?'A':'I') ? 1 : 0;
+}
+
+/***********************************************************************
+ *
+ * ftp_nbsendtransfertype()
+ *
+ * Set transfer type. We only deal with ASCII or BINARY so this function
+ * sets one of them.
+ * If the transfer type is not sent, simulate on OK response in newstate
+ */
+static CURLcode ftp_nbsendtransfertype(struct connectdata *conn,
+                                  bool ascii, ftpstate newstate)
+{
+  struct SessionHandle *data = conn->data;
+  struct FTP *ftp = conn->proto.ftp;
+  CURLcode result;
+
+  if (ftp->transfertype == (ascii?'A':'I'))
+  {
+      state(conn, newstate);
+	  return ftp_state_type_resp(conn, 200, newstate);
+  }
+  
+  NBFTPSENDF(conn, "TYPE %c", ascii?'A':'I');
+  state(conn, newstate);
+
+  /* keep track of our current transfer type */
+  ftp->transfertype = ascii?'A':'I';
   return CURLE_OK;
 }
 
@@ -3202,10 +3255,7 @@
     /* a transfer is about to take place */
 
     if(data->set.upload) {
-      NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
-      state(conn, FTP_STOR_TYPE);
-      /* keep track of our current transfer type */
-      data->ftp_in_ascii_mode = data->set.ftp_ascii;
+      if ((result=ftp_nbsendtransfertype(conn, data->set.ftp_ascii, FTP_STOR_TYPE))) return result;
     }
     else {
       /* download */
@@ -3218,16 +3268,10 @@
         /* The specified path ends with a slash, and therefore we think this
            is a directory that is requested, use LIST. But before that we
            need to set ASCII transfer mode. */
-        NBFTPSENDF(conn, "TYPE A", NULL);
-        state(conn, FTP_LIST_TYPE);
-        /* keep track of our current transfer type */
-        data->ftp_in_ascii_mode = 1;
+        if ((result=ftp_nbsendtransfertype(conn, 1, FTP_LIST_TYPE))) return result;
       }
       else {
-        NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
-        state(conn, FTP_RETR_TYPE);
-        /* keep track of our current transfer type */
-        data->ftp_in_ascii_mode = data->set.ftp_ascii;
+        if ((result=ftp_nbsendtransfertype(conn, data->set.ftp_ascii, FTP_RETR_TYPE))) return result;
       }
     }
     result = ftp_easy_statemach(conn);
@@ -3799,19 +3843,19 @@
   case FTPFILE_SINGLECWD:
     /* get the last slash */
     slash_pos=strrchr(cur_pos, '/');
-    if(slash_pos) {
+    if(slash_pos || !cur_pos || !*cur_pos) {
       ftp->dirdepth = 1; /* we consider it to be a single dir */
       ftp->dirs = (char **)calloc(1, sizeof(ftp->dirs[0]));
       if(!ftp->dirs)
         return CURLE_OUT_OF_MEMORY;
 
-      ftp->dirs[0] = curl_easy_unescape(conn->data, cur_pos,
-                                        (int)(slash_pos-cur_pos), NULL);
+	  ftp->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
+                                        slash_pos ? (int)(slash_pos-cur_pos) : 1, NULL);
       if(!ftp->dirs[0]) {
         free(ftp->dirs);
         return CURLE_OUT_OF_MEMORY;
       }
-      ftp->file = slash_pos+1;  /* the rest is the file name */
+	  ftp->file = slash_pos ? slash_pos+1 : cur_pos;  /* the rest is the file name */
     }
     else
       ftp->file = cur_pos;  /* this is a file name only */

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\http.c	2006-08-03 04:00:18.001 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\http.c	2006-08-10 16:37:45.000 +0200
@@ -1251,7 +1251,7 @@
               if(data->set.include_header)
                 writetype |= CLIENTWRITE_BODY;
 
-              result = Curl_client_write(data, writetype, line_start, perline);
+              result = Curl_client_write(conn, writetype, line_start, perline);
               if(result)
                 return result;
 

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\http_chunks.c	2005-07-13 04:00:06.000 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\http_chunks.c	2006-08-09 23:19:16.000 +0200
@@ -190,7 +190,7 @@
         case IDENTITY:
 #endif
           if(!k->ignorebody)
-            result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap,
+            result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
                                        piece);
 #ifdef HAVE_LIBZ
           break;
@@ -303,7 +303,7 @@
           return CHUNKE_STOP;
         }
         else {
-          Curl_client_write(conn->data, CLIENTWRITE_HEADER,
+          Curl_client_write(conn, CLIENTWRITE_HEADER,
                             conn->trailer, conn->trlPos);
         }
         ch->state = CHUNK_TRAILER;

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\ldap.c	2006-07-26 04:00:42.000 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\ldap.c	2006-08-10 16:37:45.000 +0200
@@ -372,9 +372,9 @@
     char  *dn = (*ldap_get_dn)(server, entryIterator);
     int i;
 
-    Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
-    Curl_client_write(data, CLIENTWRITE_BODY, (char *)dn, 0);
-    Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
+    Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+    Curl_client_write(conn, CLIENTWRITE_BODY, (char *)dn, 0);
+    Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
 
     for (attribute = (*ldap_first_attribute)(server, entryIterator, &ber);
          attribute;
@@ -387,9 +387,9 @@
       {
         for (i = 0; (vals[i] != NULL); i++)
         {
-          Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
-          Curl_client_write(data, CLIENTWRITE_BODY, (char *) attribute, 0);
-          Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
+          Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+          Curl_client_write(conn, CLIENTWRITE_BODY, (char *) attribute, 0);
+          Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
           if ((strlen(attribute) > 7) &&
               (strcmp(";binary",
                       (char *)attribute +
@@ -398,19 +398,19 @@
             val_b64_sz = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
                                             &val_b64);
             if (val_b64_sz > 0) {
-              Curl_client_write(data, CLIENTWRITE_BODY, val_b64, val_b64_sz);
+              Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
               free(val_b64);
             }
           } else
-            Curl_client_write(data, CLIENTWRITE_BODY, vals[i]->bv_val,
+            Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
                               vals[i]->bv_len);
-          Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
+          Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
         }
 
         /* Free memory used to store values */
         (*ldap_value_free_len)((void **)vals);
       }
-      Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
+      Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
 
       (*ldap_memfree)(attribute);
     }

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\sendf.c	2006-07-13 04:00:40.000 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\sendf.c	2006-08-10 16:37:45.000 +0200
@@ -367,18 +367,19 @@
    The bit pattern defines to what "streams" to write to. Body and/or header.
    The defines are in sendf.h of course.
  */
-CURLcode Curl_client_write(struct SessionHandle *data,
+CURLcode Curl_client_write(struct connectdata *conn,
                            int type,
                            char *ptr,
                            size_t len)
 {
+  struct SessionHandle *data = conn->data;
   size_t wrote;
 
   if(0 == len)
     len = strlen(ptr);
 
   if(type & CLIENTWRITE_BODY) {
-    if(data->ftp_in_ascii_mode) {
+    if((conn->protocol&PROT_FTP) && conn->proto.ftp->transfertype == 'A') {
 #ifdef CURL_DOES_CONVERSIONS
       /* convert from the network encoding */
       size_t rc;

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\sendf.h	2005-02-10 04:00:10.000 +0100
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\sendf.h	2006-08-09 23:15:29.001 +0200
@@ -47,7 +47,7 @@
 #define CLIENTWRITE_HEADER 2
 #define CLIENTWRITE_BOTH   (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
 
-CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr,
+CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
                            size_t len);
 
 /* internal read-function, does plain socket, SSL and krb4 */

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\telnet.c	2006-07-20 04:00:30.001 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\telnet.c	2006-08-10 16:37:45.000 +0200
@@ -940,7 +940,7 @@
           break;   /* Ignore \0 after CR */
         }
 
-        Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
+        Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
         continue;
 
       case CURL_TS_DATA:
@@ -954,7 +954,7 @@
           tn->telrcv_state = CURL_TS_CR;
         }
 
-        Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
+        Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
         continue;
 
       case CURL_TS_IAC:
@@ -978,7 +978,7 @@
           tn->telrcv_state = CURL_TS_SB;
           continue;
         case CURL_IAC:
-          Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
+          Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
           break;
         case CURL_DM:
         case CURL_NOP:

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\tftp.c	2006-07-30 04:00:20.000 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\tftp.c	2006-08-10 16:37:46.000 +0200
@@ -699,7 +699,7 @@
           /* Don't pass to the client empty or retransmitted packets */
           if (state->rbytes > 4 &&
               ((state->block+1) == getrpacketblock(&state->rpacket))) {
-            code = Curl_client_write(data, CLIENTWRITE_BODY,
+            code = Curl_client_write(conn, CLIENTWRITE_BODY,
                                      (char *)&state->rpacket.data[4],
                                      state->rbytes-4);
             if(code)

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\transfer.c	2006-08-01 04:00:18.001 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\transfer.c	2006-08-10 16:37:47.001 +0200
@@ -531,7 +531,7 @@
 
               headerlen = k->p - data->state.headerbuff;
 
-              result = Curl_client_write(data, writetype,
+              result = Curl_client_write(conn, writetype,
                                          data->state.headerbuff,
                                          headerlen);
               if(result)
@@ -990,7 +990,7 @@
               Curl_debug(data, CURLINFO_HEADER_IN,
                          k->p, k->hbuflen, conn);
 
-            result = Curl_client_write(data, writetype, k->p, k->hbuflen);
+            result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
             if(result)
               return result;
 
@@ -1144,7 +1144,7 @@
             if(k->badheader && !k->ignorebody) {
               /* we parsed a piece of data wrongly assuming it was a header
                  and now we output it as body instead */
-              result = Curl_client_write(data, CLIENTWRITE_BODY,
+              result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                          data->state.headerbuff,
                                          k->hbuflen);
               if(result)
@@ -1164,7 +1164,7 @@
                    Content-Encoding header. See Curl_readwrite_init; the
                    memset() call initializes k->content_encoding to zero. */
                 if(!k->ignorebody)
-                  result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
+                  result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
                                              nread);
 #ifdef HAVE_LIBZ
                 break;

--- C:\dev\sdk\curl-7.15.6-20060808\Copie de curl-7.15.6-20060808\lib\urldata.h	2006-07-26 04:00:44.000 +0200
+++ C:\dev\sdk\curl-7.15.6-20060808\lib\urldata.h	2006-08-10 16:37:47.001 +0200
@@ -362,6 +362,7 @@
   bool cwdfail;     /* set TRUE if a CWD command fails, as then we must prevent
                        caching the current directory */
   char *prevpath;   /* conn->path from the previous transfer */
+  char transfertype; /* set by ftp_transfertype for use by Curl_client_write and others (A/I or zero) */
 
   size_t nread_resp; /* number of bytes currently read of a server response */
   char *linestart_resp; /* line start pointer for the FTP server response
@@ -1183,8 +1184,6 @@
   struct UrlState state;       /* struct for fields used for state info and
                                   other dynamic purposes */
   struct PureInfo info;        /* stats, reports and info data */
-  /* set by ftp_transfertype for use by Curl_client_write and others */
-  bool ftp_in_ascii_mode;
 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
   iconv_t outbound_cd;         /* for translating to the network encoding */
   iconv_t inbound_cd;          /* for translating from the network encoding */


