Based on a patch by Armel Asselin, the FTP code no longer re-issues the TYPE

command on subsequent requests on a re-used connection unless it has to.
This commit is contained in:
Daniel Stenberg 2006-08-19 21:18:36 +00:00
parent 74a6921bc4
commit cfdcae4bc7
23 changed files with 139 additions and 99 deletions

View File

@ -7,6 +7,9 @@
Changelog Changelog
Daniel (19 August 2006) Daniel (19 August 2006)
- Based on a patch by Armel Asselin, the FTP code no longer re-issues the TYPE
command on subsequent requests on a re-used connection unless it has to.
- Armel Asselin fixed a crash in the FTP code when using SINGLECWD mode and - Armel Asselin fixed a crash in the FTP code when using SINGLECWD mode and
files in the root directory. files in the root directory.

View File

@ -11,6 +11,7 @@ Curl and libcurl 7.15.6
This release includes the following changes: This release includes the following changes:
o (FTP) libcurl avoids sending TYPE if the desired type was already set
o CURLOPT_PREQUOTE works even when CURLOPT_NOBODY is set true o CURLOPT_PREQUOTE works even when CURLOPT_NOBODY is set true
This release includes the following bugfixes: This release includes the following bugfixes:

View File

@ -62,9 +62,9 @@ enum zlibState {
}; };
static CURLcode static CURLcode
process_zlib_error(struct SessionHandle *data, process_zlib_error(struct connectdata *conn, z_stream *z)
z_stream *z)
{ {
struct SessionHandle *data = conn->data;
if (z->msg) if (z->msg)
failf (data, "Error while processing content unencoding: %s", failf (data, "Error while processing content unencoding: %s",
z->msg); z->msg);
@ -84,7 +84,7 @@ exit_zlib(z_stream *z, bool *zlib_init, CURLcode result)
} }
static CURLcode static CURLcode
inflate_stream(struct SessionHandle *data, inflate_stream(struct connectdata *conn,
struct Curl_transfer_keeper *k) struct Curl_transfer_keeper *k)
{ {
int allow_restart = 1; int allow_restart = 1;
@ -113,7 +113,7 @@ inflate_stream(struct SessionHandle *data,
if (status == Z_OK || status == Z_STREAM_END) { if (status == Z_OK || status == Z_STREAM_END) {
allow_restart = 0; allow_restart = 0;
if(DSIZ - z->avail_out) { if(DSIZ - z->avail_out) {
result = Curl_client_write(data, CLIENTWRITE_BODY, decomp, result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp,
DSIZ - z->avail_out); DSIZ - z->avail_out);
/* if !CURLE_OK, clean up, return */ /* if !CURLE_OK, clean up, return */
if (result) { if (result) {
@ -128,7 +128,7 @@ inflate_stream(struct SessionHandle *data,
if (inflateEnd(z) == Z_OK) if (inflateEnd(z) == Z_OK)
return exit_zlib(z, &k->zlib_init, result); return exit_zlib(z, &k->zlib_init, result);
else else
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z)); return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
} }
/* Done with these bytes, exit */ /* Done with these bytes, exit */
@ -143,7 +143,7 @@ inflate_stream(struct SessionHandle *data,
inflateReset(z); inflateReset(z);
if (inflateInit2(z, -MAX_WBITS) != Z_OK) { if (inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(data, z); return process_zlib_error(conn, z);
} }
z->next_in = orig_in; z->next_in = orig_in;
z->avail_in = nread; z->avail_in = nread;
@ -152,14 +152,14 @@ inflate_stream(struct SessionHandle *data,
} }
else { /* Error; exit loop, handle below */ else { /* Error; exit loop, handle below */
free(decomp); free(decomp);
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z)); return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
} }
} }
/* Will never get here */ /* Will never get here */
} }
CURLcode CURLcode
Curl_unencode_deflate_write(struct SessionHandle *data, Curl_unencode_deflate_write(struct connectdata *conn,
struct Curl_transfer_keeper *k, struct Curl_transfer_keeper *k,
ssize_t nread) ssize_t nread)
{ {
@ -173,7 +173,7 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
z->next_in = NULL; z->next_in = NULL;
z->avail_in = 0; z->avail_in = 0;
if (inflateInit(z) != Z_OK) if (inflateInit(z) != Z_OK)
return process_zlib_error(data, z); return process_zlib_error(conn, z);
k->zlib_init = ZLIB_INIT; k->zlib_init = ZLIB_INIT;
} }
@ -182,7 +182,7 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
z->avail_in = (uInt)nread; z->avail_in = (uInt)nread;
/* Now uncompress the data */ /* Now uncompress the data */
return inflate_stream(data, k); return inflate_stream(conn, k);
} }
#ifdef OLD_ZLIB_SUPPORT #ifdef OLD_ZLIB_SUPPORT
@ -272,7 +272,7 @@ static enum {
#endif #endif
CURLcode CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data, Curl_unencode_gzip_write(struct connectdata *conn,
struct Curl_transfer_keeper *k, struct Curl_transfer_keeper *k,
ssize_t nread) ssize_t nread)
{ {
@ -289,14 +289,14 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
if (strcmp(zlibVersion(), "1.2.0.4") >= 0) { if (strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if (inflateInit2(z, MAX_WBITS+32) != Z_OK) { if (inflateInit2(z, MAX_WBITS+32) != Z_OK) {
return process_zlib_error(data, z); return process_zlib_error(conn, z);
} }
k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
} else { } else {
/* we must parse the gzip header ourselves */ /* we must parse the gzip header ourselves */
if (inflateInit2(z, -MAX_WBITS) != Z_OK) { if (inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(data, z); return process_zlib_error(conn, z);
} }
k->zlib_init = ZLIB_INIT; /* Initial call state */ k->zlib_init = ZLIB_INIT; /* Initial call state */
} }
@ -307,7 +307,7 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
z->next_in = (Bytef *)k->str; z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)nread; z->avail_in = (uInt)nread;
/* Now uncompress the data */ /* Now uncompress the data */
return inflate_stream(data, k); return inflate_stream(conn, k);
} }
#ifndef OLD_ZLIB_SUPPORT #ifndef OLD_ZLIB_SUPPORT
@ -360,7 +360,7 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
case GZIP_BAD: case GZIP_BAD:
default: default:
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z)); return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
} }
} }
@ -398,7 +398,7 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
case GZIP_BAD: case GZIP_BAD:
default: default:
free(z->next_in); free(z->next_in);
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z)); return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
} }
} }
@ -418,7 +418,7 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
} }
/* We've parsed the header, now uncompress the data */ /* We've parsed the header, now uncompress the data */
return inflate_stream(data, k); return inflate_stream(conn, k);
#endif #endif
} }
#endif /* HAVE_LIBZ */ #endif /* HAVE_LIBZ */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -31,11 +31,11 @@
#define ALL_CONTENT_ENCODINGS "identity" #define ALL_CONTENT_ENCODINGS "identity"
#endif #endif
CURLcode Curl_unencode_deflate_write(struct SessionHandle *data, CURLcode Curl_unencode_deflate_write(struct connectdata *conn,
struct Curl_transfer_keeper *k, struct Curl_transfer_keeper *k,
ssize_t nread); ssize_t nread);
CURLcode CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data, Curl_unencode_gzip_write(struct connectdata *conn,
struct Curl_transfer_keeper *k, struct Curl_transfer_keeper *k,
ssize_t nread); ssize_t nread);

View File

@ -311,11 +311,11 @@ CURLcode Curl_file(struct connectdata *conn, bool *done)
CURLcode result; CURLcode result;
snprintf(buf, sizeof(data->state.buffer), snprintf(buf, sizeof(data->state.buffer),
"Content-Length: %" FORMAT_OFF_T "\r\n", expected_size); "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) if(result)
return result; return result;
result = Curl_client_write(data, CLIENTWRITE_BOTH, result = Curl_client_write(conn, CLIENTWRITE_BOTH,
(char *)"Accept-ranges: bytes\r\n", 0); (char *)"Accept-ranges: bytes\r\n", 0);
if(result) if(result)
return result; return result;
@ -339,7 +339,7 @@ CURLcode Curl_file(struct connectdata *conn, bool *done)
tm->tm_hour, tm->tm_hour,
tm->tm_min, tm->tm_min,
tm->tm_sec); tm->tm_sec);
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
} }
return result; return result;
} }
@ -377,7 +377,7 @@ CURLcode Curl_file(struct connectdata *conn, bool *done)
bytecount += nread; bytecount += nread;
res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread); res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
if(res) if(res)
return res; return res;

View File

@ -132,6 +132,10 @@ static CURLcode ftp_state_post_rest(struct connectdata *conn);
static CURLcode ftp_state_post_cwd(struct connectdata *conn); static CURLcode ftp_state_post_cwd(struct connectdata *conn);
static CURLcode ftp_state_quote(struct connectdata *conn, static CURLcode ftp_state_quote(struct connectdata *conn,
bool init, ftpstate instate); bool init, ftpstate instate);
static CURLcode ftp_nb_type(struct connectdata *conn,
bool ascii, ftpstate state);
static int ftp_need_type(struct connectdata *conn,
bool ascii);
/* easy-to-use macro: */ /* easy-to-use macro: */
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result #define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result
@ -339,7 +343,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
* for "headers". The response lines can be seen as a kind of * for "headers". The response lines can be seen as a kind of
* headers. * headers.
*/ */
result = Curl_client_write(data, CLIENTWRITE_HEADER, result = Curl_client_write(conn, CLIENTWRITE_HEADER,
ftp->linestart_resp, perline); ftp->linestart_resp, perline);
if(result) if(result)
return result; return result;
@ -570,7 +574,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* for "headers". The response lines can be seen as a kind of * for "headers". The response lines can be seen as a kind of
* headers. * headers.
*/ */
result = Curl_client_write(data, CLIENTWRITE_HEADER, result = Curl_client_write(conn, CLIENTWRITE_HEADER,
line_start, perline); line_start, perline);
if(result) if(result)
return result; return result;
@ -1313,7 +1317,8 @@ static CURLcode ftp_state_post_mdtm(struct connectdata *conn)
/* If we have selected NOBODY and HEADER, it means that we only want file /* 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 information. Which in FTP can't be much more than the file size and
date. */ date. */
if(conn->bits.no_body && data->set.include_header && ftp->file) { if(conn->bits.no_body && data->set.include_header && ftp->file &&
ftp_need_type(conn, data->set.prefer_ascii)) {
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers /* 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 may not support it! It is however the only way we have to get a file's
size! */ size! */
@ -1322,11 +1327,9 @@ static CURLcode ftp_state_post_mdtm(struct connectdata *conn)
/* Some servers return different sizes for different modes, and thus we /* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */ must set the proper type before we check the size */
NBFTPSENDF(conn, "TYPE %c", result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE);
data->set.ftp_ascii?'A':'I'); if (result)
state(conn, FTP_TYPE); return result;
/* keep track of our current transfer type */
data->ftp_in_ascii_mode = data->set.ftp_ascii;
} }
else else
result = ftp_state_post_type(conn); result = ftp_state_post_type(conn);
@ -1828,7 +1831,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
tm->tm_hour, tm->tm_hour,
tm->tm_min, tm->tm_min,
tm->tm_sec); tm->tm_sec);
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
if(result) if(result)
return result; return result;
} /* end of a ridiculous amount of conditionals */ } /* end of a ridiculous amount of conditionals */
@ -2003,7 +2006,7 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
if(-1 != filesize) { if(-1 != filesize) {
snprintf(buf, sizeof(data->state.buffer), snprintf(buf, sizeof(data->state.buffer),
"Content-Length: %" FORMAT_OFF_T "\r\n", filesize); "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) if(result)
return result; return result;
} }
@ -2030,7 +2033,7 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
case FTP_REST: case FTP_REST:
default: default:
if (ftpcode == 350) { 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); (char *)"Accept-ranges: bytes\r\n", 0);
if(result) if(result)
return result; return result;
@ -2141,7 +2144,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
*/ */
if((instate != FTP_LIST) && if((instate != FTP_LIST) &&
!data->set.ftp_ascii && !data->set.prefer_ascii &&
(ftp->downloadsize < 1)) { (ftp->downloadsize < 1)) {
/* /*
* It seems directory listings either don't show the size or very * It seems directory listings either don't show the size or very
@ -3095,7 +3098,7 @@ static CURLcode ftp_transfertype(struct connectdata *conn,
ssize_t nread; ssize_t nread;
CURLcode result; CURLcode result;
FTPSENDF(conn, "TYPE %s", ascii?"A":"I"); FTPSENDF(conn, "TYPE %c", ascii?'A':'I');
result = Curl_GetFTPResponse(&nread, conn, &ftpcode); result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result) if(result)
@ -3107,11 +3110,52 @@ static CURLcode ftp_transfertype(struct connectdata *conn,
return ascii? CURLE_FTP_COULDNT_SET_ASCII:CURLE_FTP_COULDNT_SET_BINARY; return ascii? CURLE_FTP_COULDNT_SET_ASCII:CURLE_FTP_COULDNT_SET_BINARY;
} }
/* keep track of our current transfer type */ /* keep track of our current transfer type */
data->ftp_in_ascii_mode = ascii; conn->proto.ftp->transfertype = ascii?'A':'I';
return CURLE_OK; return CURLE_OK;
} }
/***********************************************************************
*
* ftp_need_type()
*
* Returns TRUE if we in the current situation should send TYPE
*/
static int ftp_need_type(struct connectdata *conn,
bool ascii_wanted)
{
return conn->proto.ftp->transfertype != (ascii_wanted?'A':'I');
}
/***********************************************************************
*
* ftp_nb_type()
*
* Set 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_nb_type(struct connectdata *conn,
bool ascii, ftpstate newstate)
{
struct FTP *ftp = conn->proto.ftp;
CURLcode result;
int want = ascii?'A':'I';
if (ftp->transfertype == want) {
state(conn, newstate);
return ftp_state_type_resp(conn, 200, newstate);
}
NBFTPSENDF(conn, "TYPE %c", want);
state(conn, newstate);
/* keep track of our current transfer type */
ftp->transfertype = want;
return CURLE_OK;
}
/*************************************************************************** /***************************************************************************
* *
* ftp_pasv_verbose() * ftp_pasv_verbose()
@ -3207,10 +3251,10 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
/* a transfer is about to take place */ /* a transfer is about to take place */
if(data->set.upload) { if(data->set.upload) {
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I'); result = ftp_nb_type(conn, data->set.prefer_ascii,
state(conn, FTP_STOR_TYPE); FTP_STOR_TYPE);
/* keep track of our current transfer type */ if (result)
data->ftp_in_ascii_mode = data->set.ftp_ascii; return result;
} }
else { else {
/* download */ /* download */
@ -3223,16 +3267,14 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
/* The specified path ends with a slash, and therefore we think this /* The specified path ends with a slash, and therefore we think this
is a directory that is requested, use LIST. But before that we is a directory that is requested, use LIST. But before that we
need to set ASCII transfer mode. */ need to set ASCII transfer mode. */
NBFTPSENDF(conn, "TYPE A", NULL); result = ftp_nb_type(conn, 1, FTP_LIST_TYPE);
state(conn, FTP_LIST_TYPE); if (result)
/* keep track of our current transfer type */ return result;
data->ftp_in_ascii_mode = 1;
} }
else { else {
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I'); result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
state(conn, FTP_RETR_TYPE); if (result)
/* keep track of our current transfer type */ return result;
data->ftp_in_ascii_mode = data->set.ftp_ascii;
} }
} }
result = ftp_easy_statemach(conn); result = ftp_easy_statemach(conn);
@ -3621,11 +3663,11 @@ static CURLcode ftp_3rdparty_pretransfer(struct connectdata *conn)
sec_conn->xfertype = SOURCE3RD; sec_conn->xfertype = SOURCE3RD;
/* sets transfer type */ /* sets transfer type */
result = ftp_transfertype(conn, data->set.ftp_ascii); result = ftp_transfertype(conn, data->set.prefer_ascii);
if (result) if (result)
return result; return result;
result = ftp_transfertype(sec_conn, data->set.ftp_ascii); result = ftp_transfertype(sec_conn, data->set.prefer_ascii);
if (result) if (result)
return result; return result;

View File

@ -1251,7 +1251,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(data->set.include_header) if(data->set.include_header)
writetype |= CLIENTWRITE_BODY; writetype |= CLIENTWRITE_BODY;
result = Curl_client_write(data, writetype, line_start, perline); result = Curl_client_write(conn, writetype, line_start, perline);
if(result) if(result)
return result; return result;

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -190,7 +190,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
case IDENTITY: case IDENTITY:
#endif #endif
if(!k->ignorebody) if(!k->ignorebody)
result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap, result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
piece); piece);
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
break; break;
@ -198,14 +198,14 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
case DEFLATE: case DEFLATE:
/* update conn->keep.str to point to the chunk data. */ /* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap; conn->keep.str = datap;
result = Curl_unencode_deflate_write(conn->data, &conn->keep, result = Curl_unencode_deflate_write(conn, &conn->keep,
(ssize_t)piece); (ssize_t)piece);
break; break;
case GZIP: case GZIP:
/* update conn->keep.str to point to the chunk data. */ /* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap; conn->keep.str = datap;
result = Curl_unencode_gzip_write(conn->data, &conn->keep, result = Curl_unencode_gzip_write(conn, &conn->keep,
(ssize_t)piece); (ssize_t)piece);
break; break;
@ -303,7 +303,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
return CHUNKE_STOP; return CHUNKE_STOP;
} }
else { else {
Curl_client_write(conn->data, CLIENTWRITE_HEADER, Curl_client_write(conn, CLIENTWRITE_HEADER,
conn->trailer, conn->trlPos); conn->trailer, conn->trlPos);
} }
ch->state = CHUNK_TRAILER; ch->state = CHUNK_TRAILER;

View File

@ -372,9 +372,9 @@ CURLcode Curl_ldap(struct connectdata *conn, bool *done)
char *dn = (*ldap_get_dn)(server, entryIterator); char *dn = (*ldap_get_dn)(server, entryIterator);
int i; int i;
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
Curl_client_write(data, CLIENTWRITE_BODY, (char *)dn, 0); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)dn, 0);
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
for (attribute = (*ldap_first_attribute)(server, entryIterator, &ber); for (attribute = (*ldap_first_attribute)(server, entryIterator, &ber);
attribute; attribute;
@ -387,9 +387,9 @@ CURLcode Curl_ldap(struct connectdata *conn, bool *done)
{ {
for (i = 0; (vals[i] != NULL); i++) for (i = 0; (vals[i] != NULL); i++)
{ {
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
Curl_client_write(data, CLIENTWRITE_BODY, (char *) attribute, 0); Curl_client_write(conn, CLIENTWRITE_BODY, (char *) attribute, 0);
Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
if ((strlen(attribute) > 7) && if ((strlen(attribute) > 7) &&
(strcmp(";binary", (strcmp(";binary",
(char *)attribute + (char *)attribute +
@ -398,19 +398,19 @@ CURLcode Curl_ldap(struct connectdata *conn, bool *done)
val_b64_sz = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len, val_b64_sz = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
&val_b64); &val_b64);
if (val_b64_sz > 0) { 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); free(val_b64);
} }
} else } 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); 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 */ /* Free memory used to store values */
(*ldap_value_free_len)((void **)vals); (*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); (*ldap_memfree)(attribute);
} }

View File

@ -367,18 +367,19 @@ CURLcode Curl_write(struct connectdata *conn,
The bit pattern defines to what "streams" to write to. Body and/or header. The bit pattern defines to what "streams" to write to. Body and/or header.
The defines are in sendf.h of course. The defines are in sendf.h of course.
*/ */
CURLcode Curl_client_write(struct SessionHandle *data, CURLcode Curl_client_write(struct connectdata *conn,
int type, int type,
char *ptr, char *ptr,
size_t len) size_t len)
{ {
struct SessionHandle *data = conn->data;
size_t wrote; size_t wrote;
if(0 == len) if(0 == len)
len = strlen(ptr); len = strlen(ptr);
if(type & CLIENTWRITE_BODY) { if(type & CLIENTWRITE_BODY) {
if(data->ftp_in_ascii_mode) { if((conn->protocol&PROT_FTP) && conn->proto.ftp->transfertype == 'A') {
#ifdef CURL_DOES_CONVERSIONS #ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding */ /* convert from the network encoding */
size_t rc; size_t rc;

View File

@ -47,7 +47,7 @@ void Curl_failf(struct SessionHandle *, const char *fmt, ...);
#define CLIENTWRITE_HEADER 2 #define CLIENTWRITE_HEADER 2
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) #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); size_t len);
/* internal read-function, does plain socket, SSL and krb4 */ /* internal read-function, does plain socket, SSL and krb4 */

View File

@ -940,7 +940,7 @@ void telrcv(struct connectdata *conn,
break; /* Ignore \0 after CR */ break; /* Ignore \0 after CR */
} }
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
continue; continue;
case CURL_TS_DATA: case CURL_TS_DATA:
@ -954,7 +954,7 @@ void telrcv(struct connectdata *conn,
tn->telrcv_state = CURL_TS_CR; 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; continue;
case CURL_TS_IAC: case CURL_TS_IAC:
@ -978,7 +978,7 @@ void telrcv(struct connectdata *conn,
tn->telrcv_state = CURL_TS_SB; tn->telrcv_state = CURL_TS_SB;
continue; continue;
case CURL_IAC: case CURL_IAC:
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
break; break;
case CURL_DM: case CURL_DM:
case CURL_NOP: case CURL_NOP:

View File

@ -261,7 +261,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
CURLcode res = CURLE_OK; CURLcode res = CURLE_OK;
/* Set ascii mode if -B flag was used */ /* Set ascii mode if -B flag was used */
if(data->set.ftp_ascii) if(data->set.prefer_ascii)
mode = "netascii"; mode = "netascii";
switch(event) { switch(event) {
@ -699,7 +699,7 @@ CURLcode Curl_tftp(struct connectdata *conn, bool *done)
/* Don't pass to the client empty or retransmitted packets */ /* Don't pass to the client empty or retransmitted packets */
if (state->rbytes > 4 && if (state->rbytes > 4 &&
((state->block+1) == getrpacketblock(&state->rpacket))) { ((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], (char *)&state->rpacket.data[4],
state->rbytes-4); state->rbytes-4);
if(code) if(code)

View File

@ -531,7 +531,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
headerlen = k->p - data->state.headerbuff; headerlen = k->p - data->state.headerbuff;
result = Curl_client_write(data, writetype, result = Curl_client_write(conn, writetype,
data->state.headerbuff, data->state.headerbuff,
headerlen); headerlen);
if(result) if(result)
@ -990,7 +990,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
Curl_debug(data, CURLINFO_HEADER_IN, Curl_debug(data, CURLINFO_HEADER_IN,
k->p, k->hbuflen, conn); 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) if(result)
return result; return result;
@ -1144,7 +1144,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(k->badheader && !k->ignorebody) { if(k->badheader && !k->ignorebody) {
/* we parsed a piece of data wrongly assuming it was a header /* we parsed a piece of data wrongly assuming it was a header
and now we output it as body instead */ 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, data->state.headerbuff,
k->hbuflen); k->hbuflen);
if(result) if(result)
@ -1164,7 +1164,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
Content-Encoding header. See Curl_readwrite_init; the Content-Encoding header. See Curl_readwrite_init; the
memset() call initializes k->content_encoding to zero. */ memset() call initializes k->content_encoding to zero. */
if(!k->ignorebody) if(!k->ignorebody)
result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
nread); nread);
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
break; break;
@ -1172,13 +1172,13 @@ CURLcode Curl_readwrite(struct connectdata *conn,
case DEFLATE: case DEFLATE:
/* Assume CLIENTWRITE_BODY; headers are not encoded. */ /* Assume CLIENTWRITE_BODY; headers are not encoded. */
if(!k->ignorebody) if(!k->ignorebody)
result = Curl_unencode_deflate_write(data, k, nread); result = Curl_unencode_deflate_write(conn, k, nread);
break; break;
case GZIP: case GZIP:
/* Assume CLIENTWRITE_BODY; headers are not encoded. */ /* Assume CLIENTWRITE_BODY; headers are not encoded. */
if(!k->ignorebody) if(!k->ignorebody)
result = Curl_unencode_gzip_write(data, k, nread); result = Curl_unencode_gzip_write(conn, k, nread);
break; break;
case COMPRESS: case COMPRESS:
@ -1283,7 +1283,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
/* convert LF to CRLF if so asked */ /* convert LF to CRLF if so asked */
#ifdef CURL_DO_LINEEND_CONV #ifdef CURL_DO_LINEEND_CONV
/* always convert if we're FTPing in ASCII mode */ /* always convert if we're FTPing in ASCII mode */
if ((data->set.crlf) || (data->ftp_in_ascii_mode)) { if ((data->set.crlf) || (data->set.prefer_ascii)) {
#else #else
if (data->set.crlf) { if (data->set.crlf) {
#endif /* CURL_DO_LINEEND_CONV */ #endif /* CURL_DO_LINEEND_CONV */

View File

@ -612,7 +612,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* *
* Transfer using ASCII (instead of BINARY). * Transfer using ASCII (instead of BINARY).
*/ */
data->set.ftp_ascii = va_arg(param, long)?TRUE:FALSE; data->set.prefer_ascii = va_arg(param, long)?TRUE:FALSE;
break; break;
case CURLOPT_TIMECONDITION: case CURLOPT_TIMECONDITION:
/* /*
@ -3125,15 +3125,15 @@ static CURLcode CreateConnection(struct SessionHandle *data,
command = (char)toupper((int)type[6]); command = (char)toupper((int)type[6]);
switch(command) { switch(command) {
case 'A': /* ASCII mode */ case 'A': /* ASCII mode */
data->set.ftp_ascii = 1; data->set.prefer_ascii = TRUE;
break; break;
case 'D': /* directory mode */ case 'D': /* directory mode */
data->set.ftp_list_only = 1; data->set.ftp_list_only = TRUE;
break; break;
case 'I': /* binary mode */ case 'I': /* binary mode */
default: default:
/* switch off ASCII */ /* switch off ASCII */
data->set.ftp_ascii = 0; data->set.prefer_ascii = FALSE;
break; break;
} }
} }
@ -3228,13 +3228,13 @@ static CURLcode CreateConnection(struct SessionHandle *data,
switch(command) { switch(command) {
case 'A': /* ASCII mode */ case 'A': /* ASCII mode */
case 'N': /* NETASCII mode */ case 'N': /* NETASCII mode */
data->set.ftp_ascii = 1; data->set.prefer_ascii = TRUE;
break; break;
case 'O': /* octet mode */ case 'O': /* octet mode */
case 'I': /* binary mode */ case 'I': /* binary mode */
default: default:
/* switch off ASCII */ /* switch off ASCII */
data->set.ftp_ascii = 0; data->set.prefer_ascii = FALSE;
break; break;
} }
} }

View File

@ -362,6 +362,8 @@ struct FTP {
bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
caching the current directory */ caching the current directory */
char *prevpath; /* conn->path from the previous transfer */ char *prevpath; /* conn->path from the previous transfer */
char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
and others (A/I or zero) */
size_t nread_resp; /* number of bytes currently read of a server response */ size_t nread_resp; /* number of bytes currently read of a server response */
char *linestart_resp; /* line start pointer for the FTP server response char *linestart_resp; /* line start pointer for the FTP server response
@ -1114,8 +1116,8 @@ struct UserDefined {
bool printhost; /* printing host name in debug info */ bool printhost; /* printing host name in debug info */
bool get_filetime; bool get_filetime;
bool tunnel_thru_httpproxy; bool tunnel_thru_httpproxy;
bool prefer_ascii; /* ASCII rather than binary */
bool ftp_append; bool ftp_append;
bool ftp_ascii;
bool ftp_list_only; bool ftp_list_only;
bool ftp_create_missing_dirs; bool ftp_create_missing_dirs;
bool ftp_use_port; bool ftp_use_port;
@ -1184,8 +1186,6 @@ struct SessionHandle {
struct UrlState state; /* struct for fields used for state info and struct UrlState state; /* struct for fields used for state info and
other dynamic purposes */ other dynamic purposes */
struct PureInfo info; /* stats, reports and info data */ 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) #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
iconv_t outbound_cd; /* for translating to the network encoding */ iconv_t outbound_cd; /* for translating to the network encoding */
iconv_t inbound_cd; /* for translating from the network encoding */ iconv_t inbound_cd; /* for translating from the network encoding */

View File

@ -39,7 +39,6 @@ SIZE 146
RETR 146 RETR 146
CWD /nowhere/anywhere CWD /nowhere/anywhere
EPSV EPSV
TYPE I
SIZE 146 SIZE 146
RETR 146 RETR 146
QUIT QUIT

View File

@ -37,7 +37,6 @@ STOR 148
CWD /nowhere/anywhere CWD /nowhere/anywhere
CWD dir2 CWD dir2
EPSV EPSV
TYPE I
STOR 148 STOR 148
QUIT QUIT
</protocol> </protocol>

View File

@ -37,7 +37,6 @@ TYPE I
SIZE 210 SIZE 210
RETR 210 RETR 210
EPSV EPSV
TYPE I
SIZE 210 SIZE 210
RETR 210 RETR 210
QUIT QUIT

View File

@ -39,7 +39,6 @@ TYPE I
SIZE 211 SIZE 211
RETR 211 RETR 211
PASV PASV
TYPE I
SIZE 211 SIZE 211
RETR 211 RETR 211
QUIT QUIT

View File

@ -47,7 +47,6 @@ TYPE I
SIZE 212 SIZE 212
RETR 212 RETR 212
PORT 127,0,0,1, PORT 127,0,0,1,
TYPE I
SIZE 212 SIZE 212
RETR 212 RETR 212
QUIT QUIT

View File

@ -44,7 +44,6 @@ EPSV
TYPE A TYPE A
LIST LIST
EPSV EPSV
TYPE A
LIST LIST
QUIT QUIT
</protocol> </protocol>

View File

@ -31,7 +31,6 @@ EPSV
TYPE I TYPE I
STOR upload.216 STOR upload.216
EPSV EPSV
TYPE I
STOR ..anotherup STOR ..anotherup
QUIT QUIT
</protocol> </protocol>