Lines Matching refs:data

94 static void _ftp_state(struct Curl_easy *data,
98 static void _ftp_state(struct Curl_easy *data,
104 static CURLcode ftp_sendquote(struct Curl_easy *data,
107 static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn);
108 static CURLcode ftp_parse_url_path(struct Curl_easy *data);
109 static CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *done);
111 static void ftp_pasv_verbose(struct Curl_easy *data,
116 static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data);
117 static CURLcode ftp_state_mdtm(struct Curl_easy *data);
118 static CURLcode ftp_state_quote(struct Curl_easy *data,
120 static CURLcode ftp_nb_type(struct Curl_easy *data,
125 static CURLcode ftp_do(struct Curl_easy *data, bool *done);
126 static CURLcode ftp_done(struct Curl_easy *data,
128 static CURLcode ftp_connect(struct Curl_easy *data, bool *done);
129 static CURLcode ftp_disconnect(struct Curl_easy *data,
131 static CURLcode ftp_do_more(struct Curl_easy *data, int *completed);
132 static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done);
133 static int ftp_getsock(struct Curl_easy *data, struct connectdata *conn,
135 static int ftp_domore_getsock(struct Curl_easy *data,
137 static CURLcode ftp_doing(struct Curl_easy *data,
139 static CURLcode ftp_setup_connection(struct Curl_easy *data,
141 static CURLcode init_wc_data(struct Curl_easy *data);
142 static CURLcode wc_statemach(struct Curl_easy *data);
144 static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
145 static CURLcode ftp_readresp(struct Curl_easy *data,
150 static CURLcode ftp_dophase_done(struct Curl_easy *data,
213 static void close_secondarysocket(struct Curl_easy *data,
216 Curl_conn_close(data, SECONDARYSOCKET);
217 Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
258 static CURLcode AcceptServerConnect(struct Curl_easy *data)
260 struct connectdata *conn = data->conn;
278 failf(data, "Error accept()ing server connect");
281 infof(data, "Connection accepted from server");
288 result = Curl_conn_tcp_accepted_set(data, conn, SECONDARYSOCKET, &s);
292 if(data->set.fsockopt) {
296 Curl_set_in_callback(data, true);
297 error = data->set.fsockopt(data->set.sockopt_client,
300 Curl_set_in_callback(data, false);
303 close_secondarysocket(data, conn);
321 static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
327 if(data->set.accepttimeout > 0)
328 timeout_ms = data->set.accepttimeout;
333 other = Curl_timeleft(data, &now, FALSE);
340 timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata);
354 * After allowing server to connect to us from data port, this function
355 * checks both data connection for connection establishment and ctrl
359 static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
361 struct connectdata *conn = data->conn;
374 timeout_ms = ftp_timeleft_accept(data);
375 infof(data, "Checking for server connect");
378 failf(data, "Accept timeout occurred while waiting server connect");
385 infof(data, "There is negative response in cache while serv connect");
386 (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
391 /* there is pending control data still in the buffer to read */
400 failf(data, "Error while waiting for server connect");
406 infof(data, "Ready to accept data connection from server");
414 infof(data, "Ctrl conn has data while waiting for data conn");
415 (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
432 * setup transfer parameters and initiate the data transfer.
435 static CURLcode InitiateTransfer(struct Curl_easy *data)
438 struct connectdata *conn = data->conn;
441 DEBUGF(infof(data, "ftp InitiateTransfer()"));
442 if(conn->bits.ftp_use_data_ssl && data->set.ftp_use_port &&
444 result = Curl_ssl_cfilter_add(data, conn, SECONDARYSOCKET);
448 result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &connected);
455 Curl_pgrsSetUploadSize(data, data->state.infilesize);
460 Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
464 Curl_setup_transfer(data, SECONDARYSOCKET,
469 ftp_state(data, FTP_STOP);
479 * us. This function checks whether data connection is established if so it is
483 static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
489 infof(data, "Preparing for accepting server on data port");
492 Curl_pgrsTime(data, TIMER_STARTACCEPT);
494 timeout_ms = ftp_timeleft_accept(data);
497 failf(data, "Accept timeout occurred while waiting server connect");
503 result = ReceivedServerConnect(data, connected);
508 result = AcceptServerConnect(data);
512 result = InitiateTransfer(data);
518 Curl_expire(data, data->set.accepttimeout ?
519 data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
524 DEBUGF(infof(data, "ftp AllowServerConnect() -> %d", result));
536 static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
539 (void)data;
550 static CURLcode ftp_readresp(struct Curl_easy *data,
557 CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size);
561 struct connectdata *conn = data->conn;
562 char * const buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
567 code = Curl_sec_read_msg(data, conn, buf, PROT_SAFE);
570 code = Curl_sec_read_msg(data, conn, buf, PROT_PRIVATE);
573 code = Curl_sec_read_msg(data, conn, buf, PROT_CONFIDENTIAL);
583 data->info.httpcode = code;
596 infof(data, "We got a 421 - timeout");
597 ftp_state(data, FTP_STOP);
612 CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
623 struct connectdata *conn = data->conn;
642 timediff_t timeout = Curl_pp_state_timeout(data, pp, FALSE);
646 failf(data, "FTP response timeout");
661 * make sure we don't just wait for input while there is unhandled data in
673 * wait for more data anyway.
676 else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
679 failf(data, "FTP response aborted due to select/poll error: %d",
684 if(Curl_pgrsUpdate(data))
692 result = ftp_readresp(data, sockfd, pp, ftpcode, &nread);
698 data */
701 /* when we got data or there is no cache left, we reset the cache skip
756 static void _ftp_state(struct Curl_easy *data,
763 struct connectdata *conn = data->conn;
772 infof(data, "FTP %p (line %d) state change from %s to %s",
781 static CURLcode ftp_state_user(struct Curl_easy *data,
784 CURLcode result = Curl_pp_sendf(data,
790 ftp_state(data, FTP_USER);
795 static CURLcode ftp_state_pwd(struct Curl_easy *data,
798 CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
800 ftp_state(data, FTP_PWD);
806 static int ftp_getsock(struct Curl_easy *data,
810 return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
814 static int ftp_domore_getsock(struct Curl_easy *data,
818 (void)data;
825 DEBUGF(infof(data, "ftp_domore_getsock()"));
843 return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
852 static CURLcode ftp_state_cwd(struct Curl_easy *data,
860 result = ftp_state_mdtm(data);
863 DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) ||
876 result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
878 ftp_state(data, FTP_CWD);
885 result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
888 ftp_state(data, FTP_CWD);
892 result = ftp_state_mdtm(data);
905 static CURLcode ftp_state_use_port(struct Curl_easy *data,
909 struct connectdata *conn = data->conn;
927 char *string_ftpport = data->set.str[STRING_FTPPORT];
943 if(data->set.str[STRING_FTPPORT] &&
944 (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
1034 } /* data->set.ftpport */
1042 failf(data, "getsockname() failed: %s",
1064 rc = Curl_resolv(data, host, 0, FALSE, &h);
1066 (void)Curl_resolver_wait_resolv(data, &h);
1071 Curl_resolv_unlock(data, h);
1077 failf(data, "failed to resolve the address provided to PORT: %s", host);
1086 if(Curl_socket_open(data, ai, NULL, conn->transport, &portsock)) {
1093 failf(data, "socket failure: %s",
1097 DEBUGF(infof(data, "ftp_state_use_port(), opened socket"));
1119 infof(data, "bind(port=%hu) on non-local address failed: %s", port,
1124 failf(data, "getsockname() failed: %s",
1133 failf(data, "bind(port=%hu) failed: %s", port,
1146 failf(data, "bind() failed, we ran out of ports");
1154 failf(data, "getsockname() failed: %s",
1158 DEBUGF(infof(data, "ftp_state_use_port(), socket bound to port %d", port));
1163 failf(data, "socket failure: %s",
1167 DEBUGF(infof(data, "ftp_state_use_port(), listening on %d", port));
1214 result = Curl_pp_sendf(data, &ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
1218 failf(data, "Failure sending EPRT command: %s",
1242 result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target);
1244 failf(data, "Failure sending PORT command: %s",
1256 result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
1260 ftp_state(data, FTP_PORT);
1264 ftp_state(data, FTP_STOP);
1267 Curl_socket_close(data, conn, portsock);
1271 static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
1302 result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
1305 ftp_state(data, FTP_PASV);
1306 infof(data, "Connect data stream passively");
1318 static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
1321 struct FTP *ftp = data->req.p.ftp;
1322 struct connectdata *conn = data->conn;
1325 /* doesn't transfer any data */
1328 ftp_state(data, FTP_RETR_PREQUOTE);
1329 result = ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
1331 else if(data->set.ftp_use_port) {
1333 result = ftp_state_use_port(data, EPRT);
1337 if(data->set.ftp_use_pret) {
1342 result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
1343 data->set.str[STRING_CUSTOMREQUEST]?
1344 data->set.str[STRING_CUSTOMREQUEST]:
1345 (data->state.list_only?"NLST":"LIST"));
1346 else if(data->state.upload)
1347 result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
1350 result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
1353 ftp_state(data, FTP_PRET);
1356 result = ftp_state_use_pasv(data, conn);
1361 static CURLcode ftp_state_rest(struct Curl_easy *data,
1365 struct FTP *ftp = data->req.p.ftp;
1373 result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
1375 ftp_state(data, FTP_REST);
1378 result = ftp_state_prepare_transfer(data);
1383 static CURLcode ftp_state_size(struct Curl_easy *data,
1387 struct FTP *ftp = data->req.p.ftp;
1394 result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1396 ftp_state(data, FTP_SIZE);
1399 result = ftp_state_rest(data, conn);
1404 static CURLcode ftp_state_list(struct Curl_easy *data)
1407 struct FTP *ftp = data->req.p.ftp;
1408 struct connectdata *conn = data->conn;
1426 if((data->set.ftp_filemethod == FTPFILE_NOCWD) && ftp->path) {
1450 data->set.str[STRING_CUSTOMREQUEST]?
1451 data->set.str[STRING_CUSTOMREQUEST]:
1452 (data->state.list_only?"NLST":"LIST"),
1460 result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", cmd);
1464 ftp_state(data, FTP_LIST);
1469 static CURLcode ftp_state_retr_prequote(struct Curl_easy *data)
1472 return ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
1475 static CURLcode ftp_state_stor_prequote(struct Curl_easy *data)
1478 return ftp_state_quote(data, TRUE, FTP_STOR_PREQUOTE);
1481 static CURLcode ftp_state_type(struct Curl_easy *data)
1484 struct FTP *ftp = data->req.p.ftp;
1485 struct connectdata *conn = data->conn;
1491 if(data->req.no_body && ftpc->file &&
1492 ftp_need_type(conn, data->state.prefer_ascii)) {
1502 result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_TYPE);
1507 result = ftp_state_size(data, conn);
1514 static CURLcode ftp_state_mdtm(struct Curl_easy *data)
1517 struct connectdata *conn = data->conn;
1521 if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
1525 result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
1528 ftp_state(data, FTP_MDTM);
1531 result = ftp_state_type(data);
1538 static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
1542 struct connectdata *conn = data->conn;
1543 struct FTP *ftp = data->req.p.ftp;
1545 bool append = data->set.remote_append;
1547 if((data->state.resume_from && !sizechecked) ||
1548 ((data->state.resume_from > 0) && sizechecked)) {
1563 if(data->state.resume_from < 0) {
1565 result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1567 ftp_state(data, FTP_STOR_SIZE);
1576 Curl_set_in_callback(data, true);
1577 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1579 Curl_set_in_callback(data, false);
1585 failf(data, "Could not seek stream");
1592 (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ?
1594 curlx_sotouz(data->state.resume_from - passed);
1597 data->state.fread_func(scratch, 1, readthisamountnow,
1598 data->state.in);
1604 failf(data, "Failed to read data");
1607 } while(passed < data->state.resume_from);
1610 if(data->state.infilesize>0) {
1611 data->state.infilesize -= data->state.resume_from;
1613 if(data->state.infilesize <= 0) {
1614 infof(data, "File already completely uploaded");
1616 /* no data to transfer */
1617 Curl_setup_transfer(data, -1, -1, FALSE, -1);
1623 ftp_state(data, FTP_STOP);
1630 result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s",
1633 ftp_state(data, FTP_STOR);
1638 static CURLcode ftp_state_quote(struct Curl_easy *data,
1643 struct FTP *ftp = data->req.p.ftp;
1644 struct connectdata *conn = data->conn;
1652 item = data->set.quote;
1656 item = data->set.prequote;
1659 item = data->set.postquote;
1683 char *cmd = item->data;
1691 result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
1694 ftp_state(data, instate);
1704 result = ftp_state_cwd(data, conn);
1708 ftp_state(data, FTP_STOP);
1711 Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
1712 result = ftp_state_retr(data, ftpc->known_filesize);
1715 if(data->set.ignorecl || data->state.prefer_ascii) {
1728 result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
1730 ftp_state(data, FTP_RETR);
1733 result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1735 ftp_state(data, FTP_RETR_SIZE);
1741 result = ftp_state_ul_setup(data, FALSE);
1753 static CURLcode ftp_epsv_disable(struct Curl_easy *data,
1764 failf(data, "Failed EPSV attempt, exiting");
1768 infof(data, "Failed EPSV attempt. Disabling EPSV");
1771 Curl_conn_close(data, SECONDARYSOCKET);
1772 Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
1773 data->state.errorbuf = FALSE; /* allow error message to get
1775 result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
1779 ftp_state(data, FTP_PASV);
1821 static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
1824 struct connectdata *conn = data->conn;
1854 failf(data, "Illegal port number in EPSV reply");
1868 failf(data, "Weirdly formatted EPSV reply");
1893 failf(data, "Couldn't interpret the 227-response");
1898 if(data->set.ftp_skip_ip) {
1901 infof(data, "Skip %u.%u.%u.%u for data connection, reuse %s instead",
1916 return ftp_epsv_disable(data, conn);
1919 failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
1932 rc = Curl_resolv(data, host_name, conn->port, FALSE, &addr);
1936 (void)Curl_resolver_wait_resolv(data, &addr);
1942 failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
1954 Curl_conn_ev_update_info(data, conn);
1961 rc = Curl_resolv(data, ftpc->newhost, ftpc->newport, FALSE, &addr);
1964 (void)Curl_resolver_wait_resolv(data, &addr);
1969 failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
1974 result = Curl_conn_setup(data, conn, SECONDARYSOCKET, addr,
1979 Curl_resolv_unlock(data, addr); /* we're done using this address */
1981 return ftp_epsv_disable(data, conn);
1993 if(data->set.verbose)
1995 ftp_pasv_verbose(data, addr->addr, ftpc->newhost, connectport);
1997 Curl_resolv_unlock(data, addr); /* we're done using this address */
2006 ftp_state(data, FTP_STOP); /* this phase is completed */
2011 static CURLcode ftp_state_port_resp(struct Curl_easy *data,
2014 struct connectdata *conn = data->conn;
2025 infof(data, "disabling EPRT usage");
2031 failf(data, "Failed to do PORT");
2036 result = ftp_state_use_port(data, fcmd);
2039 infof(data, "Connect data stream actively");
2040 ftp_state(data, FTP_STOP); /* end of DO phase */
2041 result = ftp_dophase_done(data, FALSE);
2071 static CURLcode client_write_header(struct Curl_easy *data,
2077 * In all protocols, CLIENTWRITE_HEADER data is only passed to
2078 * the body write callback when data->set.include_header is set
2089 int save = data->set.include_header;
2090 data->set.include_header = TRUE;
2091 result = Curl_client_write(data, CLIENTWRITE_HEADER, buf, blen);
2092 data->set.include_header = save? TRUE:FALSE;
2096 static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
2100 struct FTP *ftp = data->req.p.ftp;
2101 struct connectdata *conn = data->conn;
2119 data->info.filetime = Curl_getdate_capped(timebuf);
2126 if(data->req.no_body &&
2128 data->set.get_filetime &&
2129 (data->info.filetime >= 0) ) {
2132 time_t filetime = data->info.filetime;
2150 result = client_write_header(data, headerbuf, headerbuflen);
2158 infof(data, "unsupported MDTM reply format");
2163 infof(data, "MDTM failed: file does not exist or permission problem,"
2168 if(data->set.timecondition) {
2169 if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
2170 switch(data->set.timecondition) {
2173 if(data->info.filetime <= data->set.timevalue) {
2174 infof(data, "The requested document is not new enough");
2175 ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
2176 data->info.timecond = TRUE;
2177 ftp_state(data, FTP_STOP);
2182 if(data->info.filetime > data->set.timevalue) {
2183 infof(data, "The requested document is not old enough");
2184 ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
2185 data->info.timecond = TRUE;
2186 ftp_state(data, FTP_STOP);
2193 infof(data, "Skipping time comparison");
2198 result = ftp_state_type(data);
2203 static CURLcode ftp_state_type_resp(struct Curl_easy *data,
2208 struct connectdata *conn = data->conn;
2214 failf(data, "Couldn't set desired mode");
2218 infof(data, "Got a %03d response code instead of the assumed 200",
2222 result = ftp_state_size(data, conn);
2224 result = ftp_state_list(data);
2226 result = ftp_state_retr_prequote(data);
2228 result = ftp_state_stor_prequote(data);
2233 static CURLcode ftp_state_retr(struct Curl_easy *data,
2237 struct FTP *ftp = data->req.p.ftp;
2238 struct connectdata *conn = data->conn;
2241 DEBUGF(infof(data, "ftp_state_retr()"));
2242 if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
2243 failf(data, "Maximum file size exceeded");
2248 if(data->state.resume_from) {
2252 infof(data, "ftp server doesn't support SIZE");
2261 if(data->state.resume_from< 0) {
2263 if(filesize < -data->state.resume_from) {
2264 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
2266 data->state.resume_from, filesize);
2270 ftp->downloadsize = -data->state.resume_from;
2272 data->state.resume_from = filesize - ftp->downloadsize;
2275 if(filesize < data->state.resume_from) {
2276 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
2278 data->state.resume_from, filesize);
2282 ftp->downloadsize = filesize-data->state.resume_from;
2287 /* no data to transfer */
2288 Curl_setup_transfer(data, -1, -1, FALSE, -1);
2289 infof(data, "File already completely downloaded");
2294 ftp_state(data, FTP_STOP);
2299 infof(data, "Instructs server to resume from offset %"
2300 CURL_FORMAT_CURL_OFF_T, data->state.resume_from);
2302 result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
2303 data->state.resume_from);
2305 ftp_state(data, FTP_RETR_REST);
2309 result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
2311 ftp_state(data, FTP_RETR);
2317 static CURLcode ftp_state_size_resp(struct Curl_easy *data,
2323 char *buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
2324 size_t len = data->conn->proto.ftpc.pp.nfinal;
2350 failf(data, "The file does not exist");
2361 result = client_write_header(data, clbuf, clbuflen);
2366 Curl_pgrsSetDownloadSize(data, filesize);
2367 result = ftp_state_rest(data, data->conn);
2370 Curl_pgrsSetDownloadSize(data, filesize);
2371 result = ftp_state_retr(data, filesize);
2374 data->state.resume_from = filesize;
2375 result = ftp_state_ul_setup(data, TRUE);
2381 static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
2395 result = client_write_header(data, buffer, strlen(buffer));
2400 result = ftp_state_prepare_transfer(data);
2405 failf(data, "Couldn't use REST");
2409 result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
2411 ftp_state(data, FTP_RETR);
2419 static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
2423 struct connectdata *conn = data->conn;
2426 failf(data, "Failed FTP upload: %0d", ftpcode);
2427 ftp_state(data, FTP_STOP);
2435 if(data->set.ftp_use_port) {
2438 ftp_state(data, FTP_STOP); /* no longer in STOR state */
2440 result = AllowServerConnect(data, &connected);
2446 infof(data, "Data conn was not available immediately");
2452 return InitiateTransfer(data);
2456 static CURLcode ftp_state_get_resp(struct Curl_easy *data,
2461 struct FTP *ftp = data->req.p.ftp;
2462 struct connectdata *conn = data->conn;
2468 150 Opening BINARY mode data connection for /etc/passwd (2241
2472 150 Opening ASCII mode data connection for /bin/ls
2475 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes).
2478 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes)
2496 !data->state.prefer_ascii &&
2497 !data->set.ignorecl &&
2502 * that the transferred amount of data is not the same as this line
2535 if(size > data->req.maxdownload && data->req.maxdownload > 0)
2536 size = data->req.size = data->req.maxdownload;
2537 else if((instate != FTP_LIST) && (data->state.prefer_ascii))
2540 infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T,
2541 data->req.maxdownload);
2544 infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T,
2551 if(data->set.ftp_use_port) {
2554 result = AllowServerConnect(data, &connected);
2560 infof(data, "Data conn was not available immediately");
2561 ftp_state(data, FTP_STOP);
2566 return InitiateTransfer(data);
2572 ftp_state(data, FTP_STOP); /* this phase is over */
2575 failf(data, "RETR response: %03d", ftpcode);
2586 static CURLcode ftp_state_loggedin(struct Curl_easy *data)
2589 struct connectdata *conn = data->conn;
2598 security data exchange (the TLS negotiation in this case)
2604 and the data connection should not be encapsulated.
2606 result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
2608 ftp_state(data, FTP_PBSZ);
2611 result = ftp_state_pwd(data, conn);
2617 static CURLcode ftp_state_user_resp(struct Curl_easy *data,
2621 struct connectdata *conn = data->conn;
2628 result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
2631 ftp_state(data, FTP_PASS);
2636 result = ftp_state_loggedin(data);
2639 if(data->set.str[STRING_FTP_ACCOUNT]) {
2640 result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
2641 data->set.str[STRING_FTP_ACCOUNT]);
2643 ftp_state(data, FTP_ACCT);
2646 failf(data, "ACCT requested but none available");
2656 if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
2660 Curl_pp_sendf(data, &ftpc->pp, "%s",
2661 data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
2664 ftp_state(data, FTP_USER);
2668 failf(data, "Access denied: %03d", ftpcode);
2676 static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
2681 failf(data, "ACCT rejected by server: %03d", ftpcode);
2685 result = ftp_state_loggedin(data);
2691 static CURLcode ftp_statemachine(struct Curl_easy *data,
2703 return Curl_pp_flushsend(data, pp);
2705 result = ftp_readresp(data, sock, pp, &ftpcode, &nread);
2715 if(data->set.use_ssl <= CURLUSESSL_TRY ||
2717 return ftp_state_user_resp(data, ftpcode);
2720 failf(data, "Got a %03d ftp-server response when 220 was expected",
2727 if(data->set.krb) {
2734 Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
2736 if(Curl_sec_login(data, conn)) {
2737 failf(data, "secure login failed");
2740 infof(data, "Authentication successful");
2744 if(data->set.use_ssl && !conn->bits.ftp_use_control_ssl) {
2749 switch(data->set.ftpsslauth) {
2760 failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d",
2761 (int)data->set.ftpsslauth);
2764 result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
2767 ftp_state(data, FTP_AUTH);
2770 result = ftp_state_user(data, conn);
2782 * and does not require any security data, it must respond with
2790 result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
2796 result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, &done);
2798 conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
2800 result = ftp_state_user(data, conn);
2806 result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
2811 if(data->set.use_ssl > CURLUSESSL_TRY)
2816 result = ftp_state_user(data, conn);
2822 result = ftp_state_user_resp(data, ftpcode);
2826 result = ftp_state_acct_resp(data, ftpcode);
2831 Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
2832 data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
2834 ftp_state(data, FTP_PROT);
2839 /* We have enabled SSL for the data connection! */
2841 (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
2844 else if(data->set.use_ssl > CURLUSESSL_CONTROL)
2848 if(data->set.ftp_ccc) {
2851 result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
2853 ftp_state(data, FTP_CCC);
2856 result = ftp_state_pwd(data, conn);
2862 result = Curl_ssl_cfilter_remove(data, FIRSTSOCKET);
2865 failf(data, "Failed to clear the command channel (CCC)");
2869 result = ftp_state_pwd(data, conn);
2930 result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
2937 infof(data, "Entry path is '%s'", ftpc->entrypath);
2939 data->state.most_recent_ftp_entrypath = ftpc->entrypath;
2940 ftp_state(data, FTP_SYST);
2946 infof(data, "Entry path is '%s'", ftpc->entrypath);
2948 data->state.most_recent_ftp_entrypath = ftpc->entrypath;
2953 infof(data, "Failed to figure out path");
2956 ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
2957 DEBUGF(infof(data, "protocol connect phase DONE"));
2981 result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1");
2989 ftp_state(data, FTP_NAMEFMT);
3001 ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
3002 DEBUGF(infof(data, "protocol connect phase DONE"));
3008 ftp_state_pwd(data, conn);
3012 ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
3013 DEBUGF(infof(data, "protocol connect phase DONE"));
3022 failf(data, "QUOT command failed with %03d", ftpcode);
3026 result = ftp_state_quote(data, FALSE, ftpc->state);
3032 if(data->set.ftp_create_missing_dirs &&
3040 ftpc->count3 = (data->set.ftp_create_missing_dirs == 2) ? 1 : 0;
3042 result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s",
3045 ftp_state(data, FTP_MKD);
3049 failf(data, "Server denied you to change to the given directory");
3060 result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
3063 result = ftp_state_mdtm(data);
3070 failf(data, "Failed to MKD dir: %03d", ftpcode);
3074 ftp_state(data, FTP_CWD);
3076 result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
3082 result = ftp_state_mdtm_resp(data, ftpcode);
3089 result = ftp_state_type_resp(data, ftpcode, ftpc->state);
3095 result = ftp_state_size_resp(data, ftpcode, ftpc->state);
3100 result = ftp_state_rest_resp(data, conn, ftpcode, ftpc->state);
3106 failf(data, "PRET command not accepted: %03d", ftpcode);
3109 result = ftp_state_use_pasv(data, conn);
3113 result = ftp_state_pasv_resp(data, ftpcode);
3117 result = ftp_state_port_resp(data, ftpcode);
3122 result = ftp_state_get_resp(data, ftpcode, ftpc->state);
3126 result = ftp_state_stor_resp(data, ftpcode, ftpc->state);
3132 ftp_state(data, FTP_STOP);
3142 static CURLcode ftp_multi_statemach(struct Curl_easy *data,
3145 struct connectdata *conn = data->conn;
3147 CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE);
3157 static CURLcode ftp_block_statemach(struct Curl_easy *data,
3165 result = Curl_pp_statemach(data, pp, TRUE, TRUE /* disconnecting */);
3181 static CURLcode ftp_connect(struct Curl_easy *data,
3185 struct connectdata *conn = data->conn;
3198 result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
3208 ftp_state(data, FTP_WAIT220);
3210 result = ftp_multi_statemach(data, done);
3224 static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
3227 struct connectdata *conn = data->conn;
3228 struct FTP *ftp = data->req.p.ftp;
3272 if(data->state.wildcardmatch) {
3273 if(data->set.chunk_end && ftpc->file) {
3274 Curl_set_in_callback(data, true);
3275 data->set.chunk_end(data->set.wildcardptr);
3276 Curl_set_in_callback(data, false);
3294 if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
3300 if(data->set.ftp_filemethod == FTPFILE_NOCWD)
3315 infof(data, "Remembering we are in dir \"%s\"", ftpc->prevpath);
3328 if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
3330 result = Curl_pp_sendf(data, pp, "%s", "ABOR");
3332 failf(data, "Failure sending ABOR command: %s",
3339 close_secondarysocket(data, conn);
3347 * data has been transferred. This happens when doing through NATs etc that
3355 result = Curl_GetFTPResponse(data, &nread, &ftpcode);
3360 failf(data, "control connection looks dead");
3370 if(ftpc->dont_check && data->req.maxdownload > 0) {
3373 infof(data, "partial download completed, closing connection");
3385 failf(data, "Exceeded storage allocation");
3389 failf(data, "server did not report OK, got %d", ftpcode);
3400 else if(data->state.upload) {
3401 if((-1 != data->state.infilesize) &&
3402 (data->state.infilesize != data->req.writebytecount) &&
3403 !data->set.crlf &&
3405 failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
3407 data->req.writebytecount, data->state.infilesize);
3412 if((-1 != data->req.size) &&
3413 (data->req.size != data->req.bytecount) &&
3419 ((data->req.size + data->state.crlf_conversions) !=
3420 data->req.bytecount) &&
3422 (data->req.maxdownload != data->req.bytecount)) {
3423 failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
3424 " bytes", data->req.bytecount);
3428 !data->req.bytecount &&
3429 (data->req.size>0)) {
3430 failf(data, "No data was received");
3440 if(!status && !result && !premature && data->set.postquote)
3441 result = ftp_sendquote(data, conn, data->set.postquote);
3457 CURLcode ftp_sendquote(struct Curl_easy *data,
3466 if(item->data) {
3468 char *cmd = item->data;
3483 result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
3486 result = Curl_GetFTPResponse(data, &nread, &ftpcode);
3492 failf(data, "QUOT string not accepted: %s", cmd);
3523 static CURLcode ftp_nb_type(struct Curl_easy *data,
3532 ftp_state(data, newstate);
3533 return ftp_state_type_resp(data, 200, newstate);
3536 result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
3538 ftp_state(data, newstate);
3557 ftp_pasv_verbose(struct Curl_easy *data,
3564 infof(data, "Connecting to %s (%s) port %d", newhost, buf, port);
3571 * This function shall be called when the second FTP (data) connection is
3579 static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
3581 struct connectdata *conn = data->conn;
3599 result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
3600 if(result || !Curl_conn_is_ip_connected(data, SECONDARYSOCKET)) {
3604 return ftp_epsv_disable(data, conn);
3611 ftp = data->req.p.ftp;
3616 result = ftp_multi_statemach(data, &complete);
3620 /* if we got an error or if we don't wait for a data connection return
3627 data connection and therefore we're not actually complete */
3638 result = ReceivedServerConnect(data, &serv_conned);
3640 return result; /* Failed to accept data connection */
3643 /* It looks data connection is established */
3644 result = AcceptServerConnect(data);
3647 result = InitiateTransfer(data);
3656 else if(data->state.upload) {
3657 result = ftp_nb_type(data, conn, data->state.prefer_ascii,
3662 result = ftp_multi_statemach(data, &complete);
3669 result = Curl_range(data);
3671 if(result == CURLE_OK && data->req.maxdownload >= 0) {
3678 else if(data->state.list_only || !ftpc->file) {
3685 result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE);
3692 result = ftp_nb_type(data, conn, data->state.prefer_ascii,
3698 result = ftp_multi_statemach(data, &complete);
3704 /* no data to transfer */
3705 Curl_setup_transfer(data, -1, -1, FALSE, -1);
3708 /* no waiting for the data connection so this is now complete */
3710 DEBUGF(infof(data, "DO-MORE phase ends with %d", (int)result));
3727 CURLcode ftp_perform(struct Curl_easy *data,
3734 DEBUGF(infof(data, "DO phase starts"));
3736 if(data->req.no_body) {
3738 struct FTP *ftp = data->req.p.ftp;
3745 result = ftp_state_quote(data, TRUE, FTP_QUOTE);
3750 result = ftp_multi_statemach(data, dophase_done);
3752 *connected = Curl_conn_is_connected(data->conn, SECONDARYSOCKET);
3754 infof(data, "ftp_perform ends with SECONDARY: %d", *connected);
3757 DEBUGF(infof(data, "DO phase is complete1"));
3770 static CURLcode init_wc_data(struct Curl_easy *data)
3773 struct FTP *ftp = data->req.p.ftp;
3775 struct WildcardData *wildcard = data->wildcard;
3784 result = ftp_parse_url_path(data);
3801 result = ftp_parse_url_path(data);
3809 /* allocate ftp protocol specific wildcard data */
3827 if(data->set.ftp_filemethod == FTPFILE_NOCWD)
3828 data->set.ftp_filemethod = FTPFILE_MULTICWD;
3831 result = ftp_parse_url_path(data);
3843 ftpwc->backup.write_function = data->set.fwrite_func;
3845 data->set.fwrite_func = Curl_ftp_parselist;
3847 ftpwc->backup.file_descriptor = data->set.out;
3849 data->set.out = data;
3851 infof(data, "Wildcard - Parsing started");
3865 static CURLcode wc_statemach(struct Curl_easy *data)
3867 struct WildcardData * const wildcard = data->wildcard;
3868 struct connectdata *conn = data->conn;
3874 result = init_wc_data(data);
3885 data->set.fwrite_func = ftpwc->backup.write_function;
3886 data->set.out = ftpwc->backup.file_descriptor;
3908 struct FTP *ftp = data->req.p.ftp;
3918 infof(data, "Wildcard - START of \"%s\"", finfo->filename);
3919 if(data->set.chunk_bgn) {
3921 Curl_set_in_callback(data, true);
3922 userresponse = data->set.chunk_bgn(
3923 finfo, data->set.wildcardptr, (int)wildcard->filelist.size);
3924 Curl_set_in_callback(data, false);
3927 infof(data, "Wildcard - \"%s\" skipped by user",
3944 result = ftp_parse_url_path(data);
3961 if(data->set.chunk_end) {
3962 Curl_set_in_callback(data, true);
3963 data->set.chunk_end(data->set.wildcardptr);
3964 Curl_set_in_callback(data, false);
4004 static CURLcode ftp_do(struct Curl_easy *data, bool *done)
4007 struct connectdata *conn = data->conn;
4013 if(data->state.wildcardmatch) {
4014 result = wc_statemach(data);
4015 if(data->wildcard->state == CURLWC_SKIP ||
4016 data->wildcard->state == CURLWC_DONE) {
4024 result = ftp_parse_url_path(data);
4029 result = ftp_regular_transfer(data, done);
4039 * (not data connections). We should then wait for the response from the
4044 static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn)
4049 result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT");
4051 failf(data, "Failure sending QUIT command: %s",
4055 ftp_state(data, FTP_STOP);
4059 ftp_state(data, FTP_QUIT);
4061 result = ftp_block_statemach(data, conn);
4074 static CURLcode ftp_disconnect(struct Curl_easy *data,
4092 (void)ftp_quit(data, conn); /* ignore errors on the QUIT */
4095 if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
4096 data->state.most_recent_ftp_entrypath = NULL;
4124 CURLcode ftp_parse_url_path(struct Curl_easy *data)
4127 struct FTP *ftp = data->req.p.ftp;
4128 struct connectdata *conn = data->conn;
4142 failf(data, "path contains control characters");
4146 switch(data->set.ftp_filemethod) {
4239 if(data->state.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
4241 failf(data, "Uploading to a URL without a file name");
4248 if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
4254 if(data->set.ftp_filemethod == FTPFILE_NOCWD)
4260 infof(data, "Request has same path as previous transfer");
4271 static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
4273 struct connectdata *conn = data->conn;
4274 struct FTP *ftp = data->req.p.ftp;
4279 CURLcode result = ftp_do_more(data, &completed);
4282 close_secondarysocket(data, conn);
4288 /* no data to transfer */
4289 Curl_setup_transfer(data, -1, -1, FALSE, -1);
4300 static CURLcode ftp_doing(struct Curl_easy *data,
4303 CURLcode result = ftp_multi_statemach(data, dophase_done);
4306 DEBUGF(infof(data, "DO phase failed"));
4308 result = ftp_dophase_done(data, FALSE /* not connected */);
4310 DEBUGF(infof(data, "DO phase is complete2"));
4328 CURLcode ftp_regular_transfer(struct Curl_easy *data,
4333 struct connectdata *conn = data->conn;
4335 data->req.size = -1; /* make sure this is unknown at this point */
4337 Curl_pgrsSetUploadCounter(data, 0);
4338 Curl_pgrsSetDownloadCounter(data, 0);
4339 Curl_pgrsSetUploadSize(data, -1);
4340 Curl_pgrsSetDownloadSize(data, -1);
4344 result = ftp_perform(data,
4354 result = ftp_dophase_done(data, connected);
4365 static CURLcode ftp_setup_connection(struct Curl_easy *data,
4377 /* clone connection related data that is FTP specific */
4378 if(data->set.str[STRING_FTP_ACCOUNT]) {
4379 ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]);
4385 if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) {
4387 strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
4394 data->req.p.ftp = ftp;
4396 ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
4412 data->state.prefer_ascii = TRUE;
4416 data->state.list_only = TRUE;
4422 data->state.prefer_ascii = FALSE;
4427 /* get some initial data into the ftp struct */
4431 ftpc->use_ssl = data->set.use_ssl;
4432 ftpc->ccc = data->set.ftp_ccc;