aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2005-01-21 09:32:32 +0000
committerDaniel Stenberg <daniel@haxx.se>2005-01-21 09:32:32 +0000
commit7e42cb61f75890832792c082510ec610f4c32cbe (patch)
tree3c73a5796491a7ad59dfa1d2e151141d02e276ad /lib
parent6c038680f9a0de30f2a0b60c1e02bfb74006c851 (diff)
FTP third transfer support overhaul. See CHANGES for details.
Diffstat (limited to 'lib')
-rw-r--r--lib/ftp.c58
-rw-r--r--lib/http.c5
-rw-r--r--lib/sendf.c16
-rw-r--r--lib/sendf.h3
-rw-r--r--lib/transfer.c43
-rw-r--r--lib/url.c28
-rw-r--r--lib/urldata.h14
7 files changed, 79 insertions, 88 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index ffec9c647..3f4b23fe7 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -368,7 +368,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
/* output debug output if that is requested */
if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, conn->host.dispname);
+ Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, conn);
/*
* We pass all response-lines to the callback function registered
@@ -593,7 +593,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
if(ftpcode == 530) {
/* 530 User ... access denied
(the server denies to log the specified user) */
- failf(data, "Access denied: %s", &buf[4]);
+ failf(data, "Access denied: %03d", ftpcode);
return CURLE_FTP_ACCESS_DENIED;
}
else if(ftpcode == 331) {
@@ -610,7 +610,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
or
530 Sorry, the maximum number of allowed users are already connected
*/
- failf(data, "not logged in: %s", &buf[4]);
+ failf(data, "not logged in: %03d", ftpcode);
return CURLE_FTP_USER_PASSWORD_INCORRECT;
}
else if(ftpcode/100 == 2) {
@@ -1594,7 +1594,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
}
if(!*str) {
- failf(data, "Couldn't interpret this 227-reply: %s", buf);
+ failf(data, "Couldn't interpret the 227-reply");
return CURLE_FTP_WEIRD_227_FORMAT;
}
@@ -1828,7 +1828,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
return result;
if(ftpcode>=400) {
- failf(data, "Failed FTP upload:%s", buf+3);
+ failf(data, "Failed FTP upload: %03d", ftpcode);
/* oops, we never close the sockets! */
return CURLE_FTP_COULDNT_STOR_FILE;
}
@@ -2022,7 +2022,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
return result;
if(ftpcode != 350) {
- failf(data, "Couldn't use REST: %s", buf+4);
+ failf(data, "Couldn't use REST: %03d", ftpcode);
return CURLE_FTP_COULDNT_USE_REST;
}
}
@@ -2136,7 +2136,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
ftp->no_transfer = TRUE; /* don't think we should download anything */
}
else {
- failf(data, "%s", buf+4);
+ failf(data, "RETR failed: %03d", ftpcode);
return CURLE_FTP_COULDNT_RETR_FILE;
}
}
@@ -2367,7 +2367,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
break;
if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, bytes_written, conn->host.dispname);
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, bytes_written, conn);
if(bytes_written != (ssize_t)write_len) {
write_len -= bytes_written;
@@ -2553,6 +2553,9 @@ static CURLcode ftp_3rdparty_pretransfer(struct connectdata *conn)
struct SessionHandle *data = conn->data;
struct connectdata *sec_conn = conn->sec_conn;
+ conn->xfertype = TARGET3RD;
+ sec_conn->xfertype = SOURCE3RD;
+
/* sets transfer type */
result = ftp_transfertype(conn, data->set.ftp_ascii);
if (result)
@@ -2596,7 +2599,7 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
struct connectdata *pasv_conn;
struct connectdata *port_conn;
- if (data->set.pasvHost == CURL_TARGET_PASV) {
+ if (data->set.ftpport == NULL) {
pasv_conn = conn;
port_conn = sec_conn;
}
@@ -2612,9 +2615,11 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
/* sets the passive mode */
FTPSENDF(pasv_conn, "%s", "PASV");
result = Curl_GetFTPResponse(&nread, pasv_conn, &ftpcode);
- if (result) return result;
+ if (result)
+ return result;
+
if (ftpcode != 227) {
- failf(data, "Odd return code after PASV:%s", buf + 3);
+ failf(data, "Odd return code after PASV: %03d", ftpcode);
return CURLE_FTP_WEIRD_PASV_REPLY;
}
@@ -2626,7 +2631,7 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
}
if (!*str) {
- failf(pasv_conn->data, "Couldn't interpret this 227-reply: %s", buf);
+ failf(pasv_conn->data, "Couldn't interpret the 227-reply");
return CURLE_FTP_WEIRD_227_FORMAT;
}
@@ -2640,7 +2645,7 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
return result;
if (ftpcode != 200) {
- failf(data, "PORT command attempts failed:%s", buf + 3);
+ failf(data, "PORT command attempts failed: %03d", ftpcode);
return CURLE_FTP_PORT_FAILED;
}
@@ -2648,41 +2653,44 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
stor_cmd = data->set.ftp_append?"APPE":"STOR";
/* transfers file between remote hosts */
- FTPSENDF(sec_conn, "RETR %s", data->set.source_path);
+ /* FIX: this should send a series of CWD commands and then RETR only the
+ ftp->file file. The conn->path "full path" is not unescaped. Test case
+ 230 tests this. */
+ FTPSENDF(sec_conn, "RETR %s", sec_conn->path);
- if(data->set.pasvHost == CURL_TARGET_PASV) {
+ if(!data->set.ftpport) {
result = Curl_GetFTPResponse(&nread, sec_conn, &ftpcode);
if (result)
return result;
- if (ftpcode != 150) {
- failf(data, "Failed RETR: %s", buf + 4);
+ if((ftpcode != 150) && (ftpcode != 125)) {
+ failf(data, "Failed RETR: %03d", ftpcode);
return CURLE_FTP_COULDNT_RETR_FILE;
}
- result = Curl_ftpsendf(conn, "%s %s", stor_cmd, conn->path);
+ result = Curl_ftpsendf(conn, "%s %s", stor_cmd, conn->proto.ftp->file);
if(CURLE_OK == result)
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if (result)
return result;
- if (ftpcode != 150) {
- failf(data, "Failed FTP upload: %s", buf + 4);
+ if (ftpcode >= 400) {
+ failf(data, "Failed FTP upload: %03d", ftpcode);
return CURLE_FTP_COULDNT_STOR_FILE;
}
}
else {
- result = Curl_ftpsendf(conn, "%s %s", stor_cmd, conn->path);
+ result = Curl_ftpsendf(conn, "%s %s", stor_cmd, conn->proto.ftp->file);
if(CURLE_OK == result)
result = Curl_GetFTPResponse(&nread, sec_conn, &ftpcode);
if (result)
return result;
- if (ftpcode != 150) {
- failf(data, "Failed FTP upload: %s", buf + 4);
+ if (ftpcode >= 400) {
+ failf(data, "Failed FTP upload: %03d", ftpcode);
return CURLE_FTP_COULDNT_STOR_FILE;
}
@@ -2690,8 +2698,8 @@ static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
if (result)
return result;
- if (ftpcode != 150) {
- failf(data, "Failed FTP upload: %s", buf + 4);
+ if((ftpcode != 150) && (ftpcode != 125)) {
+ failf(data, "Failed FTP upload: %03d", ftpcode);
return CURLE_FTP_COULDNT_STOR_FILE;
}
}
diff --git a/lib/http.c b/lib/http.c
index 8e4ee7d82..2618c325f 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -858,8 +858,7 @@ CURLcode add_buffer_send(send_buffer *in,
if(conn->data->set.verbose)
/* this data _may_ contain binary stuff */
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount,
- conn->host.dispname);
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount, conn);
*bytes_written += amount;
@@ -1140,7 +1139,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
/* output debug if that is requested */
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline,
- conn->host.dispname);
+ conn);
/* send the header to the callback */
writetype = CLIENTWRITE_HEADER;
diff --git a/lib/sendf.c b/lib/sendf.c
index 4094c3239..95a88a27c 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -204,8 +204,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
break;
if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written,
- conn->host.dispname);
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written, conn);
if((size_t)bytes_written != write_len) {
/* if not all was written at once, we must advance the pointer, decrease
@@ -468,18 +467,22 @@ static int showit(struct SessionHandle *data, curl_infotype type,
}
int Curl_debug(struct SessionHandle *data, curl_infotype type,
- char *ptr, size_t size, char *host)
+ char *ptr, size_t size,
+ struct connectdata *conn)
{
int rc;
- if(data->set.printhost && host) {
+ if(data->set.printhost && conn && conn->host.dispname) {
char buffer[160];
const char *t=NULL;
+ const char *w="Data";
switch (type) {
case CURLINFO_HEADER_IN:
+ w = "Header";
case CURLINFO_DATA_IN:
t = "from";
break;
case CURLINFO_HEADER_OUT:
+ w = "Header";
case CURLINFO_DATA_OUT:
t = "to";
break;
@@ -488,7 +491,10 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
}
if(t) {
- snprintf(buffer, sizeof(buffer), "[Data %s %s]", t, host);
+ snprintf(buffer, sizeof(buffer), "[%s %s %s%s]", w, t,
+ conn->xfertype==NORMAL?"":
+ (conn->xfertype==SOURCE3RD?"source ":"target "),
+ conn->host.dispname);
rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
if(rc)
return rc;
diff --git a/lib/sendf.h b/lib/sendf.h
index 0cd342bd7..77ff52e3a 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -62,7 +62,8 @@ CURLcode Curl_write(struct connectdata *conn,
/* the function used to output verbose information */
int Curl_debug(struct SessionHandle *handle, curl_infotype type,
- char *data, size_t size, char *host);
+ char *data, size_t size,
+ struct connectdata *conn);
#endif
diff --git a/lib/transfer.c b/lib/transfer.c
index 344413f0d..71338977d 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -935,7 +935,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- k->p, k->hbuflen, conn->host.dispname);
+ k->p, k->hbuflen, conn);
result = Curl_client_write(data, writetype, k->p, k->hbuflen);
if(result)
@@ -1032,14 +1032,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(data->set.verbose) {
if(k->badheader) {
Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
- k->hbuflen, conn->host.dispname);
+ k->hbuflen, conn);
if(k->badheader == HEADER_PARTHEADER)
- Curl_debug(data, CURLINFO_DATA_IN, k->str, nread,
- conn->host.dispname);
+ Curl_debug(data, CURLINFO_DATA_IN, k->str, nread, conn);
}
else
- Curl_debug(data, CURLINFO_DATA_IN, k->str, nread,
- conn->host.dispname);
+ Curl_debug(data, CURLINFO_DATA_IN, k->str, nread, conn);
}
#ifndef CURL_DISABLE_HTTP
@@ -1270,7 +1268,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(data->set.verbose)
/* show the data before we change the pointer upload_fromhere */
Curl_debug(data, CURLINFO_DATA_OUT, conn->upload_fromhere,
- bytes_written, conn->host.dispname);
+ bytes_written, conn);
if(conn->upload_present != bytes_written) {
/* we only wrote a part of the buffer (if anything), deal with it! */
@@ -2094,7 +2092,7 @@ CURLcode Curl_perform(struct SessionHandle *data)
res = Curl_connect_host(data, &conn); /* primary connection */
if(res == CURLE_OK) {
- if (data->set.source_host) /* 3rd party transfer */
+ if (data->set.source_url) /* 3rd party transfer */
res = Curl_pretransfersec(conn);
else
conn->sec_conn = NULL;
@@ -2105,7 +2103,7 @@ CURLcode Curl_perform(struct SessionHandle *data)
res = Curl_do(&conn);
/* for non 3rd party transfer only */
- if(res == CURLE_OK && !data->set.source_host) {
+ if(res == CURLE_OK && !data->set.source_url) {
res = Transfer(conn); /* now fetch that URL please */
if(res == CURLE_OK) {
@@ -2236,28 +2234,26 @@ CURLcode Curl_pretransfersec(struct connectdata *conn)
CURLcode status = CURLE_OK;
struct SessionHandle *data = conn->data;
struct connectdata *sec_conn = NULL; /* secondary connection */
- bool reuse_fresh_tmp = data->set.reuse_fresh;
-
- /* update data with source host options */
- char *url = aprintf( "%s://%s/", conn->protostr, data->set.source_host);
-
- if(!url)
- return CURLE_OUT_OF_MEMORY;
+ bool backup_reuse_fresh = data->set.reuse_fresh;
+ char *backup_userpwd = data->set.userpwd;
if(data->change.url_alloc)
free(data->change.url);
- data->change.url_alloc = TRUE;
- data->change.url = url;
- data->set.ftpport = data->set.source_port;
- data->set.userpwd = data->set.source_userpwd;
+ data->change.url_alloc = FALSE;
+ data->change.url = data->set.source_url;
+
+ /* We must never actually alter 'data->set' properties, so we restore the
+ backed up values afterwards! */
+#if 0
/* if both remote hosts are the same host - create new connection */
if (strequal(conn->host.dispname, data->set.source_host))
- /* NOTE: this is restored back to the original value after the connect is
- done */
+#endif
data->set.reuse_fresh = TRUE;
+ data->set.userpwd = data->set.source_userpwd;
+
/* secondary connection */
status = Curl_connect_host(data, &sec_conn);
if(CURLE_OK == status) {
@@ -2267,7 +2263,8 @@ CURLcode Curl_pretransfersec(struct connectdata *conn)
conn->sec_conn = sec_conn;
}
- data->set.reuse_fresh = reuse_fresh_tmp;
+ data->set.reuse_fresh = backup_reuse_fresh;
+ data->set.userpwd = backup_userpwd;
return status;
}
diff --git a/lib/url.c b/lib/url.c
index df2011ec6..8b433f606 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1360,19 +1360,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
break;
/*********** 3rd party transfer options ***********/
- case CURLOPT_SOURCE_HOST:
+ case CURLOPT_SOURCE_URL:
/*
- * Use SOURCE HOST
+ * SOURCE URL
*/
- data->set.source_host = va_arg(param, char *);
- data->set.printhost = (data->set.source_host != NULL);
- break;
-
- case CURLOPT_SOURCE_PORT:
- /*
- * Use SOURCE PORT
- */
- data->set.source_port = va_arg(param, char *);
+ data->set.source_url = va_arg(param, char *);
+ data->set.printhost = (data->set.source_url != NULL);
break;
case CURLOPT_SOURCE_USERPWD:
@@ -1382,18 +1375,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
data->set.source_userpwd = va_arg(param, char *);
break;
- case CURLOPT_SOURCE_PATH:
- /*
- * Use SOURCE PATH
- */
- data->set.source_path = va_arg(param, char *);
- break;
-
- case CURLOPT_PASV_HOST:
+ case CURLOPT_SOURCE_QUOTE:
/*
- * Indicates whether source or target host is passive
+ * List of RAW FTP commands to use after a connect
*/
- data->set.pasvHost = va_arg(param, long)?CURL_SOURCE_PASV:CURL_TARGET_PASV;
+ data->set.source_quote = va_arg(param, struct curl_slist *);
break;
case CURLOPT_SOURCE_PREQUOTE:
diff --git a/lib/urldata.h b/lib/urldata.h
index 311149d01..0cabdf23c 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -188,12 +188,6 @@ typedef enum {
NTLMSTATE_LAST
} curlntlm;
-/* for 3rd party transfers to decide which side that issues PASV */
-typedef enum {
- CURL_TARGET_PASV,
- CURL_SOURCE_PASV
-} curl_pasv_side;
-
/* Struct used for NTLM challenge-response authentication */
struct ntlmdata {
curlntlm state;
@@ -614,6 +608,8 @@ struct connectdata {
#endif
struct connectdata *sec_conn; /* secondary connection for 3rd party
transfer */
+
+ enum { NORMAL, SOURCE3RD, TARGET3RD } xfertype;
};
/* The end of connectdata. */
@@ -869,6 +865,7 @@ struct UserDefined {
struct curl_slist *quote; /* after connection is established */
struct curl_slist *postquote; /* after the transfer */
struct curl_slist *prequote; /* before the transfer, after type */
+ struct curl_slist *source_quote; /* 3rd party quote */
struct curl_slist *source_prequote; /* in 3rd party transfer mode - before
the transfer on source host */
struct curl_slist *source_postquote; /* in 3rd party transfer mode - after
@@ -901,11 +898,8 @@ struct UserDefined {
curl_off_t max_filesize; /* Maximum file size to download */
- char *source_host; /* for 3rd party transfer */
- char *source_port; /* for 3rd party transfer */
+ char *source_url; /* for 3rd party transfer */
char *source_userpwd; /* for 3rd party transfer */
- char *source_path; /* for 3rd party transfer */
- curl_pasv_side pasvHost; /* for 3rd party transfer indicates passive host */
/* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially