Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Utilities / cmcurl / lib / ftp.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24
25 #include "curl_setup.h"
26
27 #ifndef CURL_DISABLE_FTP
28
29 #ifdef HAVE_NETINET_IN_H
30 #include <netinet/in.h>
31 #endif
32 #ifdef HAVE_ARPA_INET_H
33 #include <arpa/inet.h>
34 #endif
35 #ifdef HAVE_UTSNAME_H
36 #include <sys/utsname.h>
37 #endif
38 #ifdef HAVE_NETDB_H
39 #include <netdb.h>
40 #endif
41 #ifdef __VMS
42 #include <in.h>
43 #include <inet.h>
44 #endif
45
46 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
47 #undef in_addr_t
48 #define in_addr_t unsigned long
49 #endif
50
51 #include <curl/curl.h>
52 #include "urldata.h"
53 #include "sendf.h"
54 #include "if2ip.h"
55 #include "hostip.h"
56 #include "progress.h"
57 #include "transfer.h"
58 #include "escape.h"
59 #include "http.h" /* for HTTP proxy tunnel stuff */
60 #include "ftp.h"
61 #include "fileinfo.h"
62 #include "ftplistparser.h"
63 #include "curl_range.h"
64 #include "curl_krb5.h"
65 #include "strtoofft.h"
66 #include "strcase.h"
67 #include "vtls/vtls.h"
68 #include "connect.h"
69 #include "strerror.h"
70 #include "inet_ntop.h"
71 #include "inet_pton.h"
72 #include "select.h"
73 #include "parsedate.h" /* for the week day and month names */
74 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
75 #include "multiif.h"
76 #include "url.h"
77 #include "strcase.h"
78 #include "speedcheck.h"
79 #include "warnless.h"
80 #include "http_proxy.h"
81 #include "socks.h"
82 /* The last 3 #include files should be in this order */
83 #include "curl_printf.h"
84 #include "curl_memory.h"
85 #include "memdebug.h"
86
87 #ifndef NI_MAXHOST
88 #define NI_MAXHOST 1025
89 #endif
90 #ifndef INET_ADDRSTRLEN
91 #define INET_ADDRSTRLEN 16
92 #endif
93
94 #ifdef CURL_DISABLE_VERBOSE_STRINGS
95 #define ftp_pasv_verbose(a,b,c,d)  Curl_nop_stmt
96 #endif
97
98 /* Local API functions */
99 #ifndef DEBUGBUILD
100 static void _state(struct Curl_easy *data,
101                    ftpstate newstate);
102 #define state(x,y) _state(x,y)
103 #else
104 static void _state(struct Curl_easy *data,
105                    ftpstate newstate,
106                    int lineno);
107 #define state(x,y) _state(x,y,__LINE__)
108 #endif
109
110 static CURLcode ftp_sendquote(struct Curl_easy *data,
111                               struct connectdata *conn,
112                               struct curl_slist *quote);
113 static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn);
114 static CURLcode ftp_parse_url_path(struct Curl_easy *data);
115 static CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *done);
116 #ifndef CURL_DISABLE_VERBOSE_STRINGS
117 static void ftp_pasv_verbose(struct Curl_easy *data,
118                              struct Curl_addrinfo *ai,
119                              char *newhost, /* ascii version */
120                              int port);
121 #endif
122 static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data);
123 static CURLcode ftp_state_mdtm(struct Curl_easy *data);
124 static CURLcode ftp_state_quote(struct Curl_easy *data,
125                                 bool init, ftpstate instate);
126 static CURLcode ftp_nb_type(struct Curl_easy *data,
127                             struct connectdata *conn,
128                             bool ascii, ftpstate newstate);
129 static int ftp_need_type(struct connectdata *conn,
130                          bool ascii);
131 static CURLcode ftp_do(struct Curl_easy *data, bool *done);
132 static CURLcode ftp_done(struct Curl_easy *data,
133                          CURLcode, bool premature);
134 static CURLcode ftp_connect(struct Curl_easy *data, bool *done);
135 static CURLcode ftp_disconnect(struct Curl_easy *data,
136                                struct connectdata *conn, bool dead_connection);
137 static CURLcode ftp_do_more(struct Curl_easy *data, int *completed);
138 static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done);
139 static int ftp_getsock(struct Curl_easy *data, struct connectdata *conn,
140                        curl_socket_t *socks);
141 static int ftp_domore_getsock(struct Curl_easy *data,
142                               struct connectdata *conn, curl_socket_t *socks);
143 static CURLcode ftp_doing(struct Curl_easy *data,
144                           bool *dophase_done);
145 static CURLcode ftp_setup_connection(struct Curl_easy *data,
146                                      struct connectdata *conn);
147 static CURLcode init_wc_data(struct Curl_easy *data);
148 static CURLcode wc_statemach(struct Curl_easy *data);
149 static void wc_data_dtor(void *ptr);
150 static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
151 static CURLcode ftp_readresp(struct Curl_easy *data,
152                              curl_socket_t sockfd,
153                              struct pingpong *pp,
154                              int *ftpcode,
155                              size_t *size);
156 static CURLcode ftp_dophase_done(struct Curl_easy *data,
157                                  bool connected);
158
159 /*
160  * FTP protocol handler.
161  */
162
163 const struct Curl_handler Curl_handler_ftp = {
164   "FTP",                           /* scheme */
165   ftp_setup_connection,            /* setup_connection */
166   ftp_do,                          /* do_it */
167   ftp_done,                        /* done */
168   ftp_do_more,                     /* do_more */
169   ftp_connect,                     /* connect_it */
170   ftp_multi_statemach,             /* connecting */
171   ftp_doing,                       /* doing */
172   ftp_getsock,                     /* proto_getsock */
173   ftp_getsock,                     /* doing_getsock */
174   ftp_domore_getsock,              /* domore_getsock */
175   ZERO_NULL,                       /* perform_getsock */
176   ftp_disconnect,                  /* disconnect */
177   ZERO_NULL,                       /* readwrite */
178   ZERO_NULL,                       /* connection_check */
179   ZERO_NULL,                       /* attach connection */
180   PORT_FTP,                        /* defport */
181   CURLPROTO_FTP,                   /* protocol */
182   CURLPROTO_FTP,                   /* family */
183   PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
184   PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
185   PROTOPT_WILDCARD /* flags */
186 };
187
188
189 #ifdef USE_SSL
190 /*
191  * FTPS protocol handler.
192  */
193
194 const struct Curl_handler Curl_handler_ftps = {
195   "FTPS",                          /* scheme */
196   ftp_setup_connection,            /* setup_connection */
197   ftp_do,                          /* do_it */
198   ftp_done,                        /* done */
199   ftp_do_more,                     /* do_more */
200   ftp_connect,                     /* connect_it */
201   ftp_multi_statemach,             /* connecting */
202   ftp_doing,                       /* doing */
203   ftp_getsock,                     /* proto_getsock */
204   ftp_getsock,                     /* doing_getsock */
205   ftp_domore_getsock,              /* domore_getsock */
206   ZERO_NULL,                       /* perform_getsock */
207   ftp_disconnect,                  /* disconnect */
208   ZERO_NULL,                       /* readwrite */
209   ZERO_NULL,                       /* connection_check */
210   ZERO_NULL,                       /* attach connection */
211   PORT_FTPS,                       /* defport */
212   CURLPROTO_FTPS,                  /* protocol */
213   CURLPROTO_FTP,                   /* family */
214   PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
215   PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
216 };
217 #endif
218
219 static void close_secondarysocket(struct Curl_easy *data,
220                                   struct connectdata *conn)
221 {
222   if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
223     Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
224     conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
225   }
226   conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
227 #ifndef CURL_DISABLE_PROXY
228   conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
229 #endif
230 }
231
232 /*
233  * NOTE: back in the old days, we added code in the FTP code that made NOBODY
234  * requests on files respond with headers passed to the client/stdout that
235  * looked like HTTP ones.
236  *
237  * This approach is not very elegant, it causes confusion and is error-prone.
238  * It is subject for removal at the next (or at least a future) soname bump.
239  * Until then you can test the effects of the removal by undefining the
240  * following define named CURL_FTP_HTTPSTYLE_HEAD.
241  */
242 #define CURL_FTP_HTTPSTYLE_HEAD 1
243
244 static void freedirs(struct ftp_conn *ftpc)
245 {
246   if(ftpc->dirs) {
247     int i;
248     for(i = 0; i < ftpc->dirdepth; i++) {
249       free(ftpc->dirs[i]);
250       ftpc->dirs[i] = NULL;
251     }
252     free(ftpc->dirs);
253     ftpc->dirs = NULL;
254     ftpc->dirdepth = 0;
255   }
256   Curl_safefree(ftpc->file);
257
258   /* no longer of any use */
259   Curl_safefree(ftpc->newhost);
260 }
261
262 /***********************************************************************
263  *
264  * AcceptServerConnect()
265  *
266  * After connection request is received from the server this function is
267  * called to accept the connection and close the listening socket
268  *
269  */
270 static CURLcode AcceptServerConnect(struct Curl_easy *data)
271 {
272   struct connectdata *conn = data->conn;
273   curl_socket_t sock = conn->sock[SECONDARYSOCKET];
274   curl_socket_t s = CURL_SOCKET_BAD;
275 #ifdef ENABLE_IPV6
276   struct Curl_sockaddr_storage add;
277 #else
278   struct sockaddr_in add;
279 #endif
280   curl_socklen_t size = (curl_socklen_t) sizeof(add);
281
282   if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
283     size = sizeof(add);
284
285     s = accept(sock, (struct sockaddr *) &add, &size);
286   }
287   Curl_closesocket(data, conn, sock); /* close the first socket */
288
289   if(CURL_SOCKET_BAD == s) {
290     failf(data, "Error accept()ing server connect");
291     return CURLE_FTP_PORT_FAILED;
292   }
293   infof(data, "Connection accepted from server");
294   /* when this happens within the DO state it is important that we mark us as
295      not needing DO_MORE anymore */
296   conn->bits.do_more = FALSE;
297
298   conn->sock[SECONDARYSOCKET] = s;
299   (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
300   conn->bits.sock_accepted = TRUE;
301
302   if(data->set.fsockopt) {
303     int error = 0;
304
305     /* activate callback for setting socket options */
306     Curl_set_in_callback(data, true);
307     error = data->set.fsockopt(data->set.sockopt_client,
308                                s,
309                                CURLSOCKTYPE_ACCEPT);
310     Curl_set_in_callback(data, false);
311
312     if(error) {
313       close_secondarysocket(data, conn);
314       return CURLE_ABORTED_BY_CALLBACK;
315     }
316   }
317
318   return CURLE_OK;
319
320 }
321
322 /*
323  * ftp_timeleft_accept() returns the amount of milliseconds left allowed for
324  * waiting server to connect. If the value is negative, the timeout time has
325  * already elapsed.
326  *
327  * The start time is stored in progress.t_acceptdata - as set with
328  * Curl_pgrsTime(..., TIMER_STARTACCEPT);
329  *
330  */
331 static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
332 {
333   timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
334   timediff_t other;
335   struct curltime now;
336
337   if(data->set.accepttimeout > 0)
338     timeout_ms = data->set.accepttimeout;
339
340   now = Curl_now();
341
342   /* check if the generic timeout possibly is set shorter */
343   other = Curl_timeleft(data, &now, FALSE);
344   if(other && (other < timeout_ms))
345     /* note that this also works fine for when other happens to be negative
346        due to it already having elapsed */
347     timeout_ms = other;
348   else {
349     /* subtract elapsed time */
350     timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata);
351     if(!timeout_ms)
352       /* avoid returning 0 as that means no timeout! */
353       return -1;
354   }
355
356   return timeout_ms;
357 }
358
359
360 /***********************************************************************
361  *
362  * ReceivedServerConnect()
363  *
364  * After allowing server to connect to us from data port, this function
365  * checks both data connection for connection establishment and ctrl
366  * connection for a negative response regarding a failure in connecting
367  *
368  */
369 static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
370 {
371   struct connectdata *conn = data->conn;
372   curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
373   curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
374   struct ftp_conn *ftpc = &conn->proto.ftpc;
375   struct pingpong *pp = &ftpc->pp;
376   int result;
377   timediff_t timeout_ms;
378   ssize_t nread;
379   int ftpcode;
380
381   *received = FALSE;
382
383   timeout_ms = ftp_timeleft_accept(data);
384   infof(data, "Checking for server connect");
385   if(timeout_ms < 0) {
386     /* if a timeout was already reached, bail out */
387     failf(data, "Accept timeout occurred while waiting server connect");
388     return CURLE_FTP_ACCEPT_TIMEOUT;
389   }
390
391   /* First check whether there is a cached response from server */
392   if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
393     /* Data connection could not be established, let's return */
394     infof(data, "There is negative response in cache while serv connect");
395     (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
396     return CURLE_FTP_ACCEPT_FAILED;
397   }
398
399   result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
400
401   /* see if the connection request is already here */
402   switch(result) {
403   case -1: /* error */
404     /* let's die here */
405     failf(data, "Error while waiting for server connect");
406     return CURLE_FTP_ACCEPT_FAILED;
407   case 0:  /* Server connect is not received yet */
408     break; /* loop */
409   default:
410
411     if(result & CURL_CSELECT_IN2) {
412       infof(data, "Ready to accept data connection from server");
413       *received = TRUE;
414     }
415     else if(result & CURL_CSELECT_IN) {
416       infof(data, "Ctrl conn has data while waiting for data conn");
417       (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
418
419       if(ftpcode/100 > 3)
420         return CURLE_FTP_ACCEPT_FAILED;
421
422       return CURLE_WEIRD_SERVER_REPLY;
423     }
424
425     break;
426   } /* switch() */
427
428   return CURLE_OK;
429 }
430
431
432 /***********************************************************************
433  *
434  * InitiateTransfer()
435  *
436  * After connection from server is accepted this function is called to
437  * setup transfer parameters and initiate the data transfer.
438  *
439  */
440 static CURLcode InitiateTransfer(struct Curl_easy *data)
441 {
442   CURLcode result = CURLE_OK;
443   struct connectdata *conn = data->conn;
444
445   if(conn->bits.ftp_use_data_ssl) {
446     /* since we only have a plaintext TCP connection here, we must now
447      * do the TLS stuff */
448     infof(data, "Doing the SSL/TLS handshake on the data stream");
449     result = Curl_ssl_connect(data, conn, SECONDARYSOCKET);
450     if(result)
451       return result;
452   }
453
454   if(conn->proto.ftpc.state_saved == FTP_STOR) {
455     /* When we know we're uploading a specified file, we can get the file
456        size prior to the actual upload. */
457     Curl_pgrsSetUploadSize(data, data->state.infilesize);
458
459     /* set the SO_SNDBUF for the secondary socket for those who need it */
460     Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
461
462     Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
463   }
464   else {
465     /* FTP download: */
466     Curl_setup_transfer(data, SECONDARYSOCKET,
467                         conn->proto.ftpc.retr_size_saved, FALSE, -1);
468   }
469
470   conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
471   state(data, FTP_STOP);
472
473   return CURLE_OK;
474 }
475
476 /***********************************************************************
477  *
478  * AllowServerConnect()
479  *
480  * When we've issue the PORT command, we have told the server to connect to
481  * us. This function checks whether data connection is established if so it is
482  * accepted.
483  *
484  */
485 static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
486 {
487   timediff_t timeout_ms;
488   CURLcode result = CURLE_OK;
489
490   *connected = FALSE;
491   infof(data, "Preparing for accepting server on data port");
492
493   /* Save the time we start accepting server connect */
494   Curl_pgrsTime(data, TIMER_STARTACCEPT);
495
496   timeout_ms = ftp_timeleft_accept(data);
497   if(timeout_ms < 0) {
498     /* if a timeout was already reached, bail out */
499     failf(data, "Accept timeout occurred while waiting server connect");
500     return CURLE_FTP_ACCEPT_TIMEOUT;
501   }
502
503   /* see if the connection request is already here */
504   result = ReceivedServerConnect(data, connected);
505   if(result)
506     return result;
507
508   if(*connected) {
509     result = AcceptServerConnect(data);
510     if(result)
511       return result;
512
513     result = InitiateTransfer(data);
514     if(result)
515       return result;
516   }
517   else {
518     /* Add timeout to multi handle and break out of the loop */
519     Curl_expire(data, data->set.accepttimeout ?
520                 data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
521                 EXPIRE_FTP_ACCEPT);
522   }
523
524   return result;
525 }
526
527 /* macro to check for a three-digit ftp status code at the start of the
528    given string */
529 #define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) &&       \
530                           ISDIGIT(line[2]))
531
532 /* macro to check for the last line in an FTP server response */
533 #define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
534
535 static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
536                           char *line, size_t len, int *code)
537 {
538   (void)data;
539   (void)conn;
540
541   if((len > 3) && LASTLINE(line)) {
542     *code = curlx_sltosi(strtol(line, NULL, 10));
543     return TRUE;
544   }
545
546   return FALSE;
547 }
548
549 static CURLcode ftp_readresp(struct Curl_easy *data,
550                              curl_socket_t sockfd,
551                              struct pingpong *pp,
552                              int *ftpcode, /* return the ftp-code if done */
553                              size_t *size) /* size of the response */
554 {
555   int code;
556   CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size);
557
558 #ifdef HAVE_GSSAPI
559   {
560     struct connectdata *conn = data->conn;
561     char * const buf = data->state.buffer;
562
563     /* handle the security-oriented responses 6xx ***/
564     switch(code) {
565     case 631:
566       code = Curl_sec_read_msg(data, conn, buf, PROT_SAFE);
567       break;
568     case 632:
569       code = Curl_sec_read_msg(data, conn, buf, PROT_PRIVATE);
570       break;
571     case 633:
572       code = Curl_sec_read_msg(data, conn, buf, PROT_CONFIDENTIAL);
573       break;
574     default:
575       /* normal ftp stuff we pass through! */
576       break;
577     }
578   }
579 #endif
580
581   /* store the latest code for later retrieval */
582   data->info.httpcode = code;
583
584   if(ftpcode)
585     *ftpcode = code;
586
587   if(421 == code) {
588     /* 421 means "Service not available, closing control connection." and FTP
589      * servers use it to signal that idle session timeout has been exceeded.
590      * If we ignored the response, it could end up hanging in some cases.
591      *
592      * This response code can come at any point so having it treated
593      * generically is a good idea.
594      */
595     infof(data, "We got a 421 - timeout");
596     state(data, FTP_STOP);
597     return CURLE_OPERATION_TIMEDOUT;
598   }
599
600   return result;
601 }
602
603 /* --- parse FTP server responses --- */
604
605 /*
606  * Curl_GetFTPResponse() is a BLOCKING function to read the full response
607  * from a server after a command.
608  *
609  */
610
611 CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
612                              ssize_t *nreadp, /* return number of bytes read */
613                              int *ftpcode) /* return the ftp-code */
614 {
615   /*
616    * We cannot read just one byte per read() and then go back to select() as
617    * the OpenSSL read() doesn't grok that properly.
618    *
619    * Alas, read as much as possible, split up into lines, use the ending
620    * line in a response or continue reading.  */
621
622   struct connectdata *conn = data->conn;
623   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
624   CURLcode result = CURLE_OK;
625   struct ftp_conn *ftpc = &conn->proto.ftpc;
626   struct pingpong *pp = &ftpc->pp;
627   size_t nread;
628   int cache_skip = 0;
629   int value_to_be_ignored = 0;
630
631   if(ftpcode)
632     *ftpcode = 0; /* 0 for errors */
633   else
634     /* make the pointer point to something for the rest of this function */
635     ftpcode = &value_to_be_ignored;
636
637   *nreadp = 0;
638
639   while(!*ftpcode && !result) {
640     /* check and reset timeout value every lap */
641     timediff_t timeout = Curl_pp_state_timeout(data, pp, FALSE);
642     timediff_t interval_ms;
643
644     if(timeout <= 0) {
645       failf(data, "FTP response timeout");
646       return CURLE_OPERATION_TIMEDOUT; /* already too little time */
647     }
648
649     interval_ms = 1000;  /* use 1 second timeout intervals */
650     if(timeout < interval_ms)
651       interval_ms = timeout;
652
653     /*
654      * Since this function is blocking, we need to wait here for input on the
655      * connection and only then we call the response reading function. We do
656      * timeout at least every second to make the timeout check run.
657      *
658      * A caution here is that the ftp_readresp() function has a cache that may
659      * contain pieces of a response from the previous invoke and we need to
660      * make sure we don't just wait for input while there is unhandled data in
661      * that cache. But also, if the cache is there, we call ftp_readresp() and
662      * the cache wasn't good enough to continue we must not just busy-loop
663      * around this function.
664      *
665      */
666
667     if(pp->cache && (cache_skip < 2)) {
668       /*
669        * There's a cache left since before. We then skipping the wait for
670        * socket action, unless this is the same cache like the previous round
671        * as then the cache was deemed not enough to act on and we then need to
672        * wait for more data anyway.
673        */
674     }
675     else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
676       switch(SOCKET_READABLE(sockfd, interval_ms)) {
677       case -1: /* select() error, stop reading */
678         failf(data, "FTP response aborted due to select/poll error: %d",
679               SOCKERRNO);
680         return CURLE_RECV_ERROR;
681
682       case 0: /* timeout */
683         if(Curl_pgrsUpdate(data))
684           return CURLE_ABORTED_BY_CALLBACK;
685         continue; /* just continue in our loop for the timeout duration */
686
687       default: /* for clarity */
688         break;
689       }
690     }
691     result = ftp_readresp(data, sockfd, pp, ftpcode, &nread);
692     if(result)
693       break;
694
695     if(!nread && pp->cache)
696       /* bump cache skip counter as on repeated skips we must wait for more
697          data */
698       cache_skip++;
699     else
700       /* when we got data or there is no cache left, we reset the cache skip
701          counter */
702       cache_skip = 0;
703
704     *nreadp += nread;
705
706   } /* while there's buffer left and loop is requested */
707
708   pp->pending_resp = FALSE;
709
710   return result;
711 }
712
713 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
714   /* for debug purposes */
715 static const char * const ftp_state_names[]={
716   "STOP",
717   "WAIT220",
718   "AUTH",
719   "USER",
720   "PASS",
721   "ACCT",
722   "PBSZ",
723   "PROT",
724   "CCC",
725   "PWD",
726   "SYST",
727   "NAMEFMT",
728   "QUOTE",
729   "RETR_PREQUOTE",
730   "STOR_PREQUOTE",
731   "POSTQUOTE",
732   "CWD",
733   "MKD",
734   "MDTM",
735   "TYPE",
736   "LIST_TYPE",
737   "RETR_TYPE",
738   "STOR_TYPE",
739   "SIZE",
740   "RETR_SIZE",
741   "STOR_SIZE",
742   "REST",
743   "RETR_REST",
744   "PORT",
745   "PRET",
746   "PASV",
747   "LIST",
748   "RETR",
749   "STOR",
750   "QUIT"
751 };
752 #endif
753
754 /* This is the ONLY way to change FTP state! */
755 static void _state(struct Curl_easy *data,
756                    ftpstate newstate
757 #ifdef DEBUGBUILD
758                    , int lineno
759 #endif
760   )
761 {
762   struct connectdata *conn = data->conn;
763   struct ftp_conn *ftpc = &conn->proto.ftpc;
764
765 #if defined(DEBUGBUILD)
766
767 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
768   (void) lineno;
769 #else
770   if(ftpc->state != newstate)
771     infof(data, "FTP %p (line %d) state change from %s to %s",
772           (void *)ftpc, lineno, ftp_state_names[ftpc->state],
773           ftp_state_names[newstate]);
774 #endif
775 #endif
776
777   ftpc->state = newstate;
778 }
779
780 static CURLcode ftp_state_user(struct Curl_easy *data,
781                                struct connectdata *conn)
782 {
783   CURLcode result = Curl_pp_sendf(data,
784                                   &conn->proto.ftpc.pp, "USER %s",
785                                   conn->user?conn->user:"");
786   if(!result) {
787     struct ftp_conn *ftpc = &conn->proto.ftpc;
788     ftpc->ftp_trying_alternative = FALSE;
789     state(data, FTP_USER);
790   }
791   return result;
792 }
793
794 static CURLcode ftp_state_pwd(struct Curl_easy *data,
795                               struct connectdata *conn)
796 {
797   CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
798   if(!result)
799     state(data, FTP_PWD);
800
801   return result;
802 }
803
804 /* For the FTP "protocol connect" and "doing" phases only */
805 static int ftp_getsock(struct Curl_easy *data,
806                        struct connectdata *conn,
807                        curl_socket_t *socks)
808 {
809   return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
810 }
811
812 /* For the FTP "DO_MORE" phase only */
813 static int ftp_domore_getsock(struct Curl_easy *data,
814                               struct connectdata *conn, curl_socket_t *socks)
815 {
816   struct ftp_conn *ftpc = &conn->proto.ftpc;
817   (void)data;
818
819   /* When in DO_MORE state, we could be either waiting for us to connect to a
820    * remote site, or we could wait for that site to connect to us. Or just
821    * handle ordinary commands.
822    */
823
824   if(SOCKS_STATE(conn->cnnct.state))
825     return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);
826
827   if(FTP_STOP == ftpc->state) {
828     int bits = GETSOCK_READSOCK(0);
829     bool any = FALSE;
830
831     /* if stopped and still in this state, then we're also waiting for a
832        connect on the secondary connection */
833     socks[0] = conn->sock[FIRSTSOCKET];
834
835     if(!data->set.ftp_use_port) {
836       int s;
837       int i;
838       /* PORT is used to tell the server to connect to us, and during that we
839          don't do happy eyeballs, but we do if we connect to the server */
840       for(s = 1, i = 0; i<2; i++) {
841         if(conn->tempsock[i] != CURL_SOCKET_BAD) {
842           socks[s] = conn->tempsock[i];
843           bits |= GETSOCK_WRITESOCK(s++);
844           any = TRUE;
845         }
846       }
847     }
848     if(!any) {
849       socks[1] = conn->sock[SECONDARYSOCKET];
850       bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
851     }
852
853     return bits;
854   }
855   return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
856 }
857
858 /* This is called after the FTP_QUOTE state is passed.
859
860    ftp_state_cwd() sends the range of CWD commands to the server to change to
861    the correct directory. It may also need to send MKD commands to create
862    missing ones, if that option is enabled.
863 */
864 static CURLcode ftp_state_cwd(struct Curl_easy *data,
865                               struct connectdata *conn)
866 {
867   CURLcode result = CURLE_OK;
868   struct ftp_conn *ftpc = &conn->proto.ftpc;
869
870   if(ftpc->cwddone)
871     /* already done and fine */
872     result = ftp_state_mdtm(data);
873   else {
874     /* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
875     DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) ||
876                 !(ftpc->dirdepth && ftpc->dirs[0][0] == '/'));
877
878     ftpc->count2 = 0; /* count2 counts failed CWDs */
879
880     if(conn->bits.reuse && ftpc->entrypath &&
881        /* no need to go to entrypath when we have an absolute path */
882        !(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) {
883       /* This is a re-used connection. Since we change directory to where the
884          transfer is taking place, we must first get back to the original dir
885          where we ended up after login: */
886       ftpc->cwdcount = 0; /* we count this as the first path, then we add one
887                              for all upcoming ones in the ftp->dirs[] array */
888       result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
889       if(!result)
890         state(data, FTP_CWD);
891     }
892     else {
893       if(ftpc->dirdepth) {
894         ftpc->cwdcount = 1;
895         /* issue the first CWD, the rest is sent when the CWD responses are
896            received... */
897         result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
898                                ftpc->dirs[ftpc->cwdcount -1]);
899         if(!result)
900           state(data, FTP_CWD);
901       }
902       else {
903         /* No CWD necessary */
904         result = ftp_state_mdtm(data);
905       }
906     }
907   }
908   return result;
909 }
910
911 typedef enum {
912   EPRT,
913   PORT,
914   DONE
915 } ftpport;
916
917 static CURLcode ftp_state_use_port(struct Curl_easy *data,
918                                    ftpport fcmd) /* start with this */
919 {
920   CURLcode result = CURLE_OK;
921   struct connectdata *conn = data->conn;
922   struct ftp_conn *ftpc = &conn->proto.ftpc;
923   curl_socket_t portsock = CURL_SOCKET_BAD;
924   char myhost[MAX_IPADR_LEN + 1] = "";
925
926   struct Curl_sockaddr_storage ss;
927   struct Curl_addrinfo *res, *ai;
928   curl_socklen_t sslen;
929   char hbuf[NI_MAXHOST];
930   struct sockaddr *sa = (struct sockaddr *)&ss;
931   struct sockaddr_in * const sa4 = (void *)sa;
932 #ifdef ENABLE_IPV6
933   struct sockaddr_in6 * const sa6 = (void *)sa;
934 #endif
935   static const char mode[][5] = { "EPRT", "PORT" };
936   enum resolve_t rc;
937   int error;
938   char *host = NULL;
939   char *string_ftpport = data->set.str[STRING_FTPPORT];
940   struct Curl_dns_entry *h = NULL;
941   unsigned short port_min = 0;
942   unsigned short port_max = 0;
943   unsigned short port;
944   bool possibly_non_local = TRUE;
945   char buffer[STRERROR_LEN];
946   char *addr = NULL;
947
948   /* Step 1, figure out what is requested,
949    * accepted format :
950    * (ipv4|ipv6|domain|interface)?(:port(-range)?)?
951    */
952
953   if(data->set.str[STRING_FTPPORT] &&
954      (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
955
956 #ifdef ENABLE_IPV6
957     size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
958       INET6_ADDRSTRLEN : strlen(string_ftpport);
959 #else
960     size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
961       INET_ADDRSTRLEN : strlen(string_ftpport);
962 #endif
963     char *ip_start = string_ftpport;
964     char *ip_end = NULL;
965     char *port_start = NULL;
966     char *port_sep = NULL;
967
968     addr = calloc(addrlen + 1, 1);
969     if(!addr)
970       return CURLE_OUT_OF_MEMORY;
971
972 #ifdef ENABLE_IPV6
973     if(*string_ftpport == '[') {
974       /* [ipv6]:port(-range) */
975       ip_start = string_ftpport + 1;
976       ip_end = strchr(string_ftpport, ']');
977       if(ip_end)
978         strncpy(addr, ip_start, ip_end - ip_start);
979     }
980     else
981 #endif
982       if(*string_ftpport == ':') {
983         /* :port */
984         ip_end = string_ftpport;
985       }
986       else {
987         ip_end = strchr(string_ftpport, ':');
988         if(ip_end) {
989           /* either ipv6 or (ipv4|domain|interface):port(-range) */
990 #ifdef ENABLE_IPV6
991           if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
992             /* ipv6 */
993             port_min = port_max = 0;
994             strcpy(addr, string_ftpport);
995             ip_end = NULL; /* this got no port ! */
996           }
997           else
998 #endif
999             /* (ipv4|domain|interface):port(-range) */
1000             strncpy(addr, string_ftpport, ip_end - ip_start);
1001         }
1002         else
1003           /* ipv4|interface */
1004           strcpy(addr, string_ftpport);
1005       }
1006
1007     /* parse the port */
1008     if(ip_end) {
1009       port_start = strchr(ip_end, ':');
1010       if(port_start) {
1011         port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
1012         port_sep = strchr(port_start, '-');
1013         if(port_sep) {
1014           port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
1015         }
1016         else
1017           port_max = port_min;
1018       }
1019     }
1020
1021     /* correct errors like:
1022      *  :1234-1230
1023      *  :-4711,  in this case port_min is (unsigned)-1,
1024      *           therefore port_min > port_max for all cases
1025      *           but port_max = (unsigned)-1
1026      */
1027     if(port_min > port_max)
1028       port_min = port_max = 0;
1029
1030
1031     if(*addr != '\0') {
1032       /* attempt to get the address of the given interface name */
1033       switch(Curl_if2ip(conn->ip_addr->ai_family,
1034 #ifdef ENABLE_IPV6
1035                         Curl_ipv6_scope(conn->ip_addr->ai_addr),
1036                         conn->scope_id,
1037 #endif
1038                         addr, hbuf, sizeof(hbuf))) {
1039         case IF2IP_NOT_FOUND:
1040           /* not an interface, use the given string as host name instead */
1041           host = addr;
1042           break;
1043         case IF2IP_AF_NOT_SUPPORTED:
1044           return CURLE_FTP_PORT_FAILED;
1045         case IF2IP_FOUND:
1046           host = hbuf; /* use the hbuf for host name */
1047       }
1048     }
1049     else
1050       /* there was only a port(-range) given, default the host */
1051       host = NULL;
1052   } /* data->set.ftpport */
1053
1054   if(!host) {
1055     const char *r;
1056     /* not an interface and not a host name, get default by extracting
1057        the IP from the control connection */
1058     sslen = sizeof(ss);
1059     if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
1060       failf(data, "getsockname() failed: %s",
1061             Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1062       free(addr);
1063       return CURLE_FTP_PORT_FAILED;
1064     }
1065     switch(sa->sa_family) {
1066 #ifdef ENABLE_IPV6
1067     case AF_INET6:
1068       r = Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
1069       break;
1070 #endif
1071     default:
1072       r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
1073       break;
1074     }
1075     if(!r)
1076       return CURLE_FTP_PORT_FAILED;
1077     host = hbuf; /* use this host name */
1078     possibly_non_local = FALSE; /* we know it is local now */
1079   }
1080
1081   /* resolv ip/host to ip */
1082   rc = Curl_resolv(data, host, 0, FALSE, &h);
1083   if(rc == CURLRESOLV_PENDING)
1084     (void)Curl_resolver_wait_resolv(data, &h);
1085   if(h) {
1086     res = h->addr;
1087     /* when we return from this function, we can forget about this entry
1088        to we can unlock it now already */
1089     Curl_resolv_unlock(data, h);
1090   } /* (h) */
1091   else
1092     res = NULL; /* failure! */
1093
1094   if(!res) {
1095     failf(data, "failed to resolve the address provided to PORT: %s", host);
1096     free(addr);
1097     return CURLE_FTP_PORT_FAILED;
1098   }
1099
1100   free(addr);
1101   host = NULL;
1102
1103   /* step 2, create a socket for the requested address */
1104
1105   portsock = CURL_SOCKET_BAD;
1106   error = 0;
1107   for(ai = res; ai; ai = ai->ai_next) {
1108     result = Curl_socket(data, ai, NULL, &portsock);
1109     if(result) {
1110       error = SOCKERRNO;
1111       continue;
1112     }
1113     break;
1114   }
1115   if(!ai) {
1116     failf(data, "socket failure: %s",
1117           Curl_strerror(error, buffer, sizeof(buffer)));
1118     return CURLE_FTP_PORT_FAILED;
1119   }
1120
1121   /* step 3, bind to a suitable local address */
1122
1123   memcpy(sa, ai->ai_addr, ai->ai_addrlen);
1124   sslen = ai->ai_addrlen;
1125
1126   for(port = port_min; port <= port_max;) {
1127     if(sa->sa_family == AF_INET)
1128       sa4->sin_port = htons(port);
1129 #ifdef ENABLE_IPV6
1130     else
1131       sa6->sin6_port = htons(port);
1132 #endif
1133     /* Try binding the given address. */
1134     if(bind(portsock, sa, sslen) ) {
1135       /* It failed. */
1136       error = SOCKERRNO;
1137       if(possibly_non_local && (error == EADDRNOTAVAIL)) {
1138         /* The requested bind address is not local.  Use the address used for
1139          * the control connection instead and restart the port loop
1140          */
1141         infof(data, "bind(port=%hu) on non-local address failed: %s", port,
1142               Curl_strerror(error, buffer, sizeof(buffer)));
1143
1144         sslen = sizeof(ss);
1145         if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
1146           failf(data, "getsockname() failed: %s",
1147                 Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1148           Curl_closesocket(data, conn, portsock);
1149           return CURLE_FTP_PORT_FAILED;
1150         }
1151         port = port_min;
1152         possibly_non_local = FALSE; /* don't try this again */
1153         continue;
1154       }
1155       if(error != EADDRINUSE && error != EACCES) {
1156         failf(data, "bind(port=%hu) failed: %s", port,
1157               Curl_strerror(error, buffer, sizeof(buffer)));
1158         Curl_closesocket(data, conn, portsock);
1159         return CURLE_FTP_PORT_FAILED;
1160       }
1161     }
1162     else
1163       break;
1164
1165     port++;
1166   }
1167
1168   /* maybe all ports were in use already*/
1169   if(port > port_max) {
1170     failf(data, "bind() failed, we ran out of ports");
1171     Curl_closesocket(data, conn, portsock);
1172     return CURLE_FTP_PORT_FAILED;
1173   }
1174
1175   /* get the name again after the bind() so that we can extract the
1176      port number it uses now */
1177   sslen = sizeof(ss);
1178   if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
1179     failf(data, "getsockname() failed: %s",
1180           Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1181     Curl_closesocket(data, conn, portsock);
1182     return CURLE_FTP_PORT_FAILED;
1183   }
1184
1185   /* step 4, listen on the socket */
1186
1187   if(listen(portsock, 1)) {
1188     failf(data, "socket failure: %s",
1189           Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1190     Curl_closesocket(data, conn, portsock);
1191     return CURLE_FTP_PORT_FAILED;
1192   }
1193
1194   /* step 5, send the proper FTP command */
1195
1196   /* get a plain printable version of the numerical address to work with
1197      below */
1198   Curl_printable_address(ai, myhost, sizeof(myhost));
1199
1200 #ifdef ENABLE_IPV6
1201   if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
1202     /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
1203        request and enable EPRT again! */
1204     conn->bits.ftp_use_eprt = TRUE;
1205 #endif
1206
1207   for(; fcmd != DONE; fcmd++) {
1208
1209     if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
1210       /* if disabled, goto next */
1211       continue;
1212
1213     if((PORT == fcmd) && sa->sa_family != AF_INET)
1214       /* PORT is IPv4 only */
1215       continue;
1216
1217     switch(sa->sa_family) {
1218     case AF_INET:
1219       port = ntohs(sa4->sin_port);
1220       break;
1221 #ifdef ENABLE_IPV6
1222     case AF_INET6:
1223       port = ntohs(sa6->sin6_port);
1224       break;
1225 #endif
1226     default:
1227       continue; /* might as well skip this */
1228     }
1229
1230     if(EPRT == fcmd) {
1231       /*
1232        * Two fine examples from RFC2428;
1233        *
1234        * EPRT |1|132.235.1.2|6275|
1235        *
1236        * EPRT |2|1080::8:800:200C:417A|5282|
1237        */
1238
1239       result = Curl_pp_sendf(data, &ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
1240                              sa->sa_family == AF_INET?1:2,
1241                              myhost, port);
1242       if(result) {
1243         failf(data, "Failure sending EPRT command: %s",
1244               curl_easy_strerror(result));
1245         Curl_closesocket(data, conn, portsock);
1246         /* don't retry using PORT */
1247         ftpc->count1 = PORT;
1248         /* bail out */
1249         state(data, FTP_STOP);
1250         return result;
1251       }
1252       break;
1253     }
1254     if(PORT == fcmd) {
1255       /* large enough for [IP address],[num],[num] */
1256       char target[sizeof(myhost) + 20];
1257       char *source = myhost;
1258       char *dest = target;
1259
1260       /* translate x.x.x.x to x,x,x,x */
1261       while(source && *source) {
1262         if(*source == '.')
1263           *dest = ',';
1264         else
1265           *dest = *source;
1266         dest++;
1267         source++;
1268       }
1269       *dest = 0;
1270       msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
1271
1272       result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target);
1273       if(result) {
1274         failf(data, "Failure sending PORT command: %s",
1275               curl_easy_strerror(result));
1276         Curl_closesocket(data, conn, portsock);
1277         /* bail out */
1278         state(data, FTP_STOP);
1279         return result;
1280       }
1281       break;
1282     }
1283   }
1284
1285   /* store which command was sent */
1286   ftpc->count1 = fcmd;
1287
1288   close_secondarysocket(data, conn);
1289
1290   /* we set the secondary socket variable to this for now, it is only so that
1291      the cleanup function will close it in case we fail before the true
1292      secondary stuff is made */
1293   conn->sock[SECONDARYSOCKET] = portsock;
1294
1295   /* this tcpconnect assignment below is a hackish work-around to make the
1296      multi interface with active FTP work - as it will not wait for a
1297      (passive) connect in Curl_is_connected().
1298
1299      The *proper* fix is to make sure that the active connection from the
1300      server is done in a non-blocking way. Currently, it is still BLOCKING.
1301   */
1302   conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
1303
1304   state(data, FTP_PORT);
1305   return result;
1306 }
1307
1308 static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
1309                                    struct connectdata *conn)
1310 {
1311   struct ftp_conn *ftpc = &conn->proto.ftpc;
1312   CURLcode result = CURLE_OK;
1313   /*
1314     Here's the executive summary on what to do:
1315
1316     PASV is RFC959, expect:
1317     227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
1318
1319     LPSV is RFC1639, expect:
1320     228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
1321
1322     EPSV is RFC2428, expect:
1323     229 Entering Extended Passive Mode (|||port|)
1324
1325   */
1326
1327   static const char mode[][5] = { "EPSV", "PASV" };
1328   int modeoff;
1329
1330 #ifdef PF_INET6
1331   if(!conn->bits.ftp_use_epsv && conn->bits.ipv6)
1332     /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the
1333        request and enable EPSV again! */
1334     conn->bits.ftp_use_epsv = TRUE;
1335 #endif
1336
1337   modeoff = conn->bits.ftp_use_epsv?0:1;
1338
1339   result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
1340   if(!result) {
1341     ftpc->count1 = modeoff;
1342     state(data, FTP_PASV);
1343     infof(data, "Connect data stream passively");
1344   }
1345   return result;
1346 }
1347
1348 /*
1349  * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc.
1350  *
1351  * REST is the last command in the chain of commands when a "head"-like
1352  * request is made. Thus, if an actual transfer is to be made this is where we
1353  * take off for real.
1354  */
1355 static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
1356 {
1357   CURLcode result = CURLE_OK;
1358   struct FTP *ftp = data->req.p.ftp;
1359   struct connectdata *conn = data->conn;
1360
1361   if(ftp->transfer != PPTRANSFER_BODY) {
1362     /* doesn't transfer any data */
1363
1364     /* still possibly do PRE QUOTE jobs */
1365     state(data, FTP_RETR_PREQUOTE);
1366     result = ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
1367   }
1368   else if(data->set.ftp_use_port) {
1369     /* We have chosen to use the PORT (or similar) command */
1370     result = ftp_state_use_port(data, EPRT);
1371   }
1372   else {
1373     /* We have chosen (this is default) to use the PASV (or similar) command */
1374     if(data->set.ftp_use_pret) {
1375       /* The user has requested that we send a PRET command
1376          to prepare the server for the upcoming PASV */
1377       struct ftp_conn *ftpc = &conn->proto.ftpc;
1378       if(!conn->proto.ftpc.file)
1379         result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
1380                                data->set.str[STRING_CUSTOMREQUEST]?
1381                                data->set.str[STRING_CUSTOMREQUEST]:
1382                                (data->state.list_only?"NLST":"LIST"));
1383       else if(data->set.upload)
1384         result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
1385                                conn->proto.ftpc.file);
1386       else
1387         result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
1388                                conn->proto.ftpc.file);
1389       if(!result)
1390         state(data, FTP_PRET);
1391     }
1392     else
1393       result = ftp_state_use_pasv(data, conn);
1394   }
1395   return result;
1396 }
1397
1398 static CURLcode ftp_state_rest(struct Curl_easy *data,
1399                                struct connectdata *conn)
1400 {
1401   CURLcode result = CURLE_OK;
1402   struct FTP *ftp = data->req.p.ftp;
1403   struct ftp_conn *ftpc = &conn->proto.ftpc;
1404
1405   if((ftp->transfer != PPTRANSFER_BODY) && ftpc->file) {
1406     /* if a "head"-like request is being made (on a file) */
1407
1408     /* Determine if server can respond to REST command and therefore
1409        whether it supports range */
1410     result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
1411     if(!result)
1412       state(data, FTP_REST);
1413   }
1414   else
1415     result = ftp_state_prepare_transfer(data);
1416
1417   return result;
1418 }
1419
1420 static CURLcode ftp_state_size(struct Curl_easy *data,
1421                                struct connectdata *conn)
1422 {
1423   CURLcode result = CURLE_OK;
1424   struct FTP *ftp = data->req.p.ftp;
1425   struct ftp_conn *ftpc = &conn->proto.ftpc;
1426
1427   if((ftp->transfer == PPTRANSFER_INFO) && ftpc->file) {
1428     /* if a "head"-like request is being made (on a file) */
1429
1430     /* we know ftpc->file is a valid pointer to a file name */
1431     result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1432     if(!result)
1433       state(data, FTP_SIZE);
1434   }
1435   else
1436     result = ftp_state_rest(data, conn);
1437
1438   return result;
1439 }
1440
1441 static CURLcode ftp_state_list(struct Curl_easy *data)
1442 {
1443   CURLcode result = CURLE_OK;
1444   struct FTP *ftp = data->req.p.ftp;
1445   struct connectdata *conn = data->conn;
1446
1447   /* If this output is to be machine-parsed, the NLST command might be better
1448      to use, since the LIST command output is not specified or standard in any
1449      way. It has turned out that the NLST list output is not the same on all
1450      servers either... */
1451
1452   /*
1453      if FTPFILE_NOCWD was specified, we should add the path
1454      as argument for the LIST / NLST / or custom command.
1455      Whether the server will support this, is uncertain.
1456
1457      The other ftp_filemethods will CWD into dir/dir/ first and
1458      then just do LIST (in that case: nothing to do here)
1459   */
1460   char *lstArg = NULL;
1461   char *cmd;
1462
1463   if((data->set.ftp_filemethod == FTPFILE_NOCWD) && ftp->path) {
1464     /* url-decode before evaluation: e.g. paths starting/ending with %2f */
1465     const char *slashPos = NULL;
1466     char *rawPath = NULL;
1467     result = Curl_urldecode(ftp->path, 0, &rawPath, NULL, REJECT_CTRL);
1468     if(result)
1469       return result;
1470
1471     slashPos = strrchr(rawPath, '/');
1472     if(slashPos) {
1473       /* chop off the file part if format is dir/file otherwise remove
1474          the trailing slash for dir/dir/ except for absolute path / */
1475       size_t n = slashPos - rawPath;
1476       if(n == 0)
1477         ++n;
1478
1479       lstArg = rawPath;
1480       lstArg[n] = '\0';
1481     }
1482     else
1483       free(rawPath);
1484   }
1485
1486   cmd = aprintf("%s%s%s",
1487                 data->set.str[STRING_CUSTOMREQUEST]?
1488                 data->set.str[STRING_CUSTOMREQUEST]:
1489                 (data->state.list_only?"NLST":"LIST"),
1490                 lstArg? " ": "",
1491                 lstArg? lstArg: "");
1492   free(lstArg);
1493
1494   if(!cmd)
1495     return CURLE_OUT_OF_MEMORY;
1496
1497   result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", cmd);
1498   free(cmd);
1499
1500   if(!result)
1501     state(data, FTP_LIST);
1502
1503   return result;
1504 }
1505
1506 static CURLcode ftp_state_retr_prequote(struct Curl_easy *data)
1507 {
1508   /* We've sent the TYPE, now we must send the list of prequote strings */
1509   return ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
1510 }
1511
1512 static CURLcode ftp_state_stor_prequote(struct Curl_easy *data)
1513 {
1514   /* We've sent the TYPE, now we must send the list of prequote strings */
1515   return ftp_state_quote(data, TRUE, FTP_STOR_PREQUOTE);
1516 }
1517
1518 static CURLcode ftp_state_type(struct Curl_easy *data)
1519 {
1520   CURLcode result = CURLE_OK;
1521   struct FTP *ftp = data->req.p.ftp;
1522   struct connectdata *conn = data->conn;
1523   struct ftp_conn *ftpc = &conn->proto.ftpc;
1524
1525   /* If we have selected NOBODY and HEADER, it means that we only want file
1526      information. Which in FTP can't be much more than the file size and
1527      date. */
1528   if(data->set.opt_no_body && ftpc->file &&
1529      ftp_need_type(conn, data->state.prefer_ascii)) {
1530     /* The SIZE command is _not_ RFC 959 specified, and therefore many servers
1531        may not support it! It is however the only way we have to get a file's
1532        size! */
1533
1534     ftp->transfer = PPTRANSFER_INFO;
1535     /* this means no actual transfer will be made */
1536
1537     /* Some servers return different sizes for different modes, and thus we
1538        must set the proper type before we check the size */
1539     result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_TYPE);
1540     if(result)
1541       return result;
1542   }
1543   else
1544     result = ftp_state_size(data, conn);
1545
1546   return result;
1547 }
1548
1549 /* This is called after the CWD commands have been done in the beginning of
1550    the DO phase */
1551 static CURLcode ftp_state_mdtm(struct Curl_easy *data)
1552 {
1553   CURLcode result = CURLE_OK;
1554   struct connectdata *conn = data->conn;
1555   struct ftp_conn *ftpc = &conn->proto.ftpc;
1556
1557   /* Requested time of file or time-depended transfer? */
1558   if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
1559
1560     /* we have requested to get the modified-time of the file, this is a white
1561        spot as the MDTM is not mentioned in RFC959 */
1562     result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
1563
1564     if(!result)
1565       state(data, FTP_MDTM);
1566   }
1567   else
1568     result = ftp_state_type(data);
1569
1570   return result;
1571 }
1572
1573
1574 /* This is called after the TYPE and possible quote commands have been sent */
1575 static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
1576                                    bool sizechecked)
1577 {
1578   CURLcode result = CURLE_OK;
1579   struct connectdata *conn = data->conn;
1580   struct FTP *ftp = data->req.p.ftp;
1581   struct ftp_conn *ftpc = &conn->proto.ftpc;
1582   bool append = data->set.remote_append;
1583
1584   if((data->state.resume_from && !sizechecked) ||
1585      ((data->state.resume_from > 0) && sizechecked)) {
1586     /* we're about to continue the uploading of a file */
1587     /* 1. get already existing file's size. We use the SIZE command for this
1588        which may not exist in the server!  The SIZE command is not in
1589        RFC959. */
1590
1591     /* 2. This used to set REST. But since we can do append, we
1592        don't another ftp command. We just skip the source file
1593        offset and then we APPEND the rest on the file instead */
1594
1595     /* 3. pass file-size number of bytes in the source file */
1596     /* 4. lower the infilesize counter */
1597     /* => transfer as usual */
1598     int seekerr = CURL_SEEKFUNC_OK;
1599
1600     if(data->state.resume_from < 0) {
1601       /* Got no given size to start from, figure it out */
1602       result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1603       if(!result)
1604         state(data, FTP_STOR_SIZE);
1605       return result;
1606     }
1607
1608     /* enable append */
1609     append = TRUE;
1610
1611     /* Let's read off the proper amount of bytes from the input. */
1612     if(conn->seek_func) {
1613       Curl_set_in_callback(data, true);
1614       seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
1615                                 SEEK_SET);
1616       Curl_set_in_callback(data, false);
1617     }
1618
1619     if(seekerr != CURL_SEEKFUNC_OK) {
1620       curl_off_t passed = 0;
1621       if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1622         failf(data, "Could not seek stream");
1623         return CURLE_FTP_COULDNT_USE_REST;
1624       }
1625       /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
1626       do {
1627         size_t readthisamountnow =
1628           (data->state.resume_from - passed > data->set.buffer_size) ?
1629           (size_t)data->set.buffer_size :
1630           curlx_sotouz(data->state.resume_from - passed);
1631
1632         size_t actuallyread =
1633           data->state.fread_func(data->state.buffer, 1, readthisamountnow,
1634                                  data->state.in);
1635
1636         passed += actuallyread;
1637         if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1638           /* this checks for greater-than only to make sure that the
1639              CURL_READFUNC_ABORT return code still aborts */
1640           failf(data, "Failed to read data");
1641           return CURLE_FTP_COULDNT_USE_REST;
1642         }
1643       } while(passed < data->state.resume_from);
1644     }
1645     /* now, decrease the size of the read */
1646     if(data->state.infilesize>0) {
1647       data->state.infilesize -= data->state.resume_from;
1648
1649       if(data->state.infilesize <= 0) {
1650         infof(data, "File already completely uploaded");
1651
1652         /* no data to transfer */
1653         Curl_setup_transfer(data, -1, -1, FALSE, -1);
1654
1655         /* Set ->transfer so that we won't get any error in
1656          * ftp_done() because we didn't transfer anything! */
1657         ftp->transfer = PPTRANSFER_NONE;
1658
1659         state(data, FTP_STOP);
1660         return CURLE_OK;
1661       }
1662     }
1663     /* we've passed, proceed as normal */
1664   } /* resume_from */
1665
1666   result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s",
1667                          ftpc->file);
1668   if(!result)
1669     state(data, FTP_STOR);
1670
1671   return result;
1672 }
1673
1674 static CURLcode ftp_state_quote(struct Curl_easy *data,
1675                                 bool init,
1676                                 ftpstate instate)
1677 {
1678   CURLcode result = CURLE_OK;
1679   struct FTP *ftp = data->req.p.ftp;
1680   struct connectdata *conn = data->conn;
1681   struct ftp_conn *ftpc = &conn->proto.ftpc;
1682   bool quote = FALSE;
1683   struct curl_slist *item;
1684
1685   switch(instate) {
1686   case FTP_QUOTE:
1687   default:
1688     item = data->set.quote;
1689     break;
1690   case FTP_RETR_PREQUOTE:
1691   case FTP_STOR_PREQUOTE:
1692     item = data->set.prequote;
1693     break;
1694   case FTP_POSTQUOTE:
1695     item = data->set.postquote;
1696     break;
1697   }
1698
1699   /*
1700    * This state uses:
1701    * 'count1' to iterate over the commands to send
1702    * 'count2' to store whether to allow commands to fail
1703    */
1704
1705   if(init)
1706     ftpc->count1 = 0;
1707   else
1708     ftpc->count1++;
1709
1710   if(item) {
1711     int i = 0;
1712
1713     /* Skip count1 items in the linked list */
1714     while((i< ftpc->count1) && item) {
1715       item = item->next;
1716       i++;
1717     }
1718     if(item) {
1719       char *cmd = item->data;
1720       if(cmd[0] == '*') {
1721         cmd++;
1722         ftpc->count2 = 1; /* the sent command is allowed to fail */
1723       }
1724       else
1725         ftpc->count2 = 0; /* failure means cancel operation */
1726
1727       result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
1728       if(result)
1729         return result;
1730       state(data, instate);
1731       quote = TRUE;
1732     }
1733   }
1734
1735   if(!quote) {
1736     /* No more quote to send, continue to ... */
1737     switch(instate) {
1738     case FTP_QUOTE:
1739     default:
1740       result = ftp_state_cwd(data, conn);
1741       break;
1742     case FTP_RETR_PREQUOTE:
1743       if(ftp->transfer != PPTRANSFER_BODY)
1744         state(data, FTP_STOP);
1745       else {
1746         if(ftpc->known_filesize != -1) {
1747           Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
1748           result = ftp_state_retr(data, ftpc->known_filesize);
1749         }
1750         else {
1751           if(data->set.ignorecl || data->state.prefer_ascii) {
1752             /* 'ignorecl' is used to support download of growing files.  It
1753                prevents the state machine from requesting the file size from
1754                the server.  With an unknown file size the download continues
1755                until the server terminates it, otherwise the client stops if
1756                the received byte count exceeds the reported file size.  Set
1757                option CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this
1758                behavior.
1759
1760                In addition: asking for the size for 'TYPE A' transfers is not
1761                constructive since servers don't report the converted size. So
1762                skip it.
1763             */
1764             result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
1765             if(!result)
1766               state(data, FTP_RETR);
1767           }
1768           else {
1769             result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1770             if(!result)
1771               state(data, FTP_RETR_SIZE);
1772           }
1773         }
1774       }
1775       break;
1776     case FTP_STOR_PREQUOTE:
1777       result = ftp_state_ul_setup(data, FALSE);
1778       break;
1779     case FTP_POSTQUOTE:
1780       break;
1781     }
1782   }
1783
1784   return result;
1785 }
1786
1787 /* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
1788    problems */
1789 static CURLcode ftp_epsv_disable(struct Curl_easy *data,
1790                                  struct connectdata *conn)
1791 {
1792   CURLcode result = CURLE_OK;
1793
1794   if(conn->bits.ipv6
1795 #ifndef CURL_DISABLE_PROXY
1796      && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)
1797 #endif
1798     ) {
1799     /* We can't disable EPSV when doing IPv6, so this is instead a fail */
1800     failf(data, "Failed EPSV attempt, exiting");
1801     return CURLE_WEIRD_SERVER_REPLY;
1802   }
1803
1804   infof(data, "Failed EPSV attempt. Disabling EPSV");
1805   /* disable it for next transfer */
1806   conn->bits.ftp_use_epsv = FALSE;
1807   data->state.errorbuf = FALSE; /* allow error message to get
1808                                          rewritten */
1809   result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
1810   if(!result) {
1811     conn->proto.ftpc.count1++;
1812     /* remain in/go to the FTP_PASV state */
1813     state(data, FTP_PASV);
1814   }
1815   return result;
1816 }
1817
1818
1819 static char *control_address(struct connectdata *conn)
1820 {
1821   /* Returns the control connection IP address.
1822      If a proxy tunnel is used, returns the original host name instead, because
1823      the effective control connection address is the proxy address,
1824      not the ftp host. */
1825 #ifndef CURL_DISABLE_PROXY
1826   if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
1827     return conn->host.name;
1828 #endif
1829   return conn->primary_ip;
1830 }
1831
1832 static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
1833                                     int ftpcode)
1834 {
1835   struct connectdata *conn = data->conn;
1836   struct ftp_conn *ftpc = &conn->proto.ftpc;
1837   CURLcode result;
1838   struct Curl_dns_entry *addr = NULL;
1839   enum resolve_t rc;
1840   unsigned short connectport; /* the local port connect() should use! */
1841   char *str = &data->state.buffer[4];  /* start on the first letter */
1842
1843   /* if we come here again, make sure the former name is cleared */
1844   Curl_safefree(ftpc->newhost);
1845
1846   if((ftpc->count1 == 0) &&
1847      (ftpcode == 229)) {
1848     /* positive EPSV response */
1849     char *ptr = strchr(str, '(');
1850     if(ptr) {
1851       unsigned int num;
1852       char separator[4];
1853       ptr++;
1854       if(5 == sscanf(ptr, "%c%c%c%u%c",
1855                      &separator[0],
1856                      &separator[1],
1857                      &separator[2],
1858                      &num,
1859                      &separator[3])) {
1860         const char sep1 = separator[0];
1861         int i;
1862
1863         /* The four separators should be identical, or else this is an oddly
1864            formatted reply and we bail out immediately. */
1865         for(i = 1; i<4; i++) {
1866           if(separator[i] != sep1) {
1867             ptr = NULL; /* set to NULL to signal error */
1868             break;
1869           }
1870         }
1871         if(num > 0xffff) {
1872           failf(data, "Illegal port number in EPSV reply");
1873           return CURLE_FTP_WEIRD_PASV_REPLY;
1874         }
1875         if(ptr) {
1876           ftpc->newport = (unsigned short)(num & 0xffff);
1877           ftpc->newhost = strdup(control_address(conn));
1878           if(!ftpc->newhost)
1879             return CURLE_OUT_OF_MEMORY;
1880         }
1881       }
1882       else
1883         ptr = NULL;
1884     }
1885     if(!ptr) {
1886       failf(data, "Weirdly formatted EPSV reply");
1887       return CURLE_FTP_WEIRD_PASV_REPLY;
1888     }
1889   }
1890   else if((ftpc->count1 == 1) &&
1891           (ftpcode == 227)) {
1892     /* positive PASV response */
1893     unsigned int ip[4] = {0, 0, 0, 0};
1894     unsigned int port[2] = {0, 0};
1895
1896     /*
1897      * Scan for a sequence of six comma-separated numbers and use them as
1898      * IP+port indicators.
1899      *
1900      * Found reply-strings include:
1901      * "227 Entering Passive Mode (127,0,0,1,4,51)"
1902      * "227 Data transfer will passively listen to 127,0,0,1,4,51"
1903      * "227 Entering passive mode. 127,0,0,1,4,51"
1904      */
1905     while(*str) {
1906       if(6 == sscanf(str, "%u,%u,%u,%u,%u,%u",
1907                      &ip[0], &ip[1], &ip[2], &ip[3],
1908                      &port[0], &port[1]))
1909         break;
1910       str++;
1911     }
1912
1913     if(!*str || (ip[0] > 255) || (ip[1] > 255)  || (ip[2] > 255)  ||
1914        (ip[3] > 255) || (port[0] > 255)  || (port[1] > 255) ) {
1915       failf(data, "Couldn't interpret the 227-response");
1916       return CURLE_FTP_WEIRD_227_FORMAT;
1917     }
1918
1919     /* we got OK from server */
1920     if(data->set.ftp_skip_ip) {
1921       /* told to ignore the remotely given IP but instead use the host we used
1922          for the control connection */
1923       infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead",
1924             ip[0], ip[1], ip[2], ip[3],
1925             conn->host.name);
1926       ftpc->newhost = strdup(control_address(conn));
1927     }
1928     else
1929       ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
1930
1931     if(!ftpc->newhost)
1932       return CURLE_OUT_OF_MEMORY;
1933
1934     ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
1935   }
1936   else if(ftpc->count1 == 0) {
1937     /* EPSV failed, move on to PASV */
1938     return ftp_epsv_disable(data, conn);
1939   }
1940   else {
1941     failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
1942     return CURLE_FTP_WEIRD_PASV_REPLY;
1943   }
1944
1945 #ifndef CURL_DISABLE_PROXY
1946   if(conn->bits.proxy) {
1947     /*
1948      * This connection uses a proxy and we need to connect to the proxy again
1949      * here. We don't want to rely on a former host lookup that might've
1950      * expired now, instead we remake the lookup here and now!
1951      */
1952     const char * const host_name = conn->bits.socksproxy ?
1953       conn->socks_proxy.host.name : conn->http_proxy.host.name;
1954     rc = Curl_resolv(data, host_name, (int)conn->port, FALSE, &addr);
1955     if(rc == CURLRESOLV_PENDING)
1956       /* BLOCKING, ignores the return code but 'addr' will be NULL in
1957          case of failure */
1958       (void)Curl_resolver_wait_resolv(data, &addr);
1959
1960     connectport =
1961       (unsigned short)conn->port; /* we connect to the proxy's port */
1962
1963     if(!addr) {
1964       failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
1965       return CURLE_COULDNT_RESOLVE_PROXY;
1966     }
1967   }
1968   else
1969 #endif
1970   {
1971     /* normal, direct, ftp connection */
1972     DEBUGASSERT(ftpc->newhost);
1973
1974     /* postponed address resolution in case of tcp fastopen */
1975     if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) {
1976       Curl_conninfo_remote(data, conn, conn->sock[FIRSTSOCKET]);
1977       Curl_safefree(ftpc->newhost);
1978       ftpc->newhost = strdup(control_address(conn));
1979       if(!ftpc->newhost)
1980         return CURLE_OUT_OF_MEMORY;
1981     }
1982
1983     rc = Curl_resolv(data, ftpc->newhost, ftpc->newport, FALSE, &addr);
1984     if(rc == CURLRESOLV_PENDING)
1985       /* BLOCKING */
1986       (void)Curl_resolver_wait_resolv(data, &addr);
1987
1988     connectport = ftpc->newport; /* we connect to the remote port */
1989
1990     if(!addr) {
1991       failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
1992       return CURLE_FTP_CANT_GET_HOST;
1993     }
1994   }
1995
1996   conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
1997   result = Curl_connecthost(data, conn, addr);
1998
1999   if(result) {
2000     Curl_resolv_unlock(data, addr); /* we're done using this address */
2001     if(ftpc->count1 == 0 && ftpcode == 229)
2002       return ftp_epsv_disable(data, conn);
2003
2004     return result;
2005   }
2006
2007
2008   /*
2009    * When this is used from the multi interface, this might've returned with
2010    * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
2011    * connect to connect.
2012    */
2013
2014   if(data->set.verbose)
2015     /* this just dumps information about this second connection */
2016     ftp_pasv_verbose(data, addr->addr, ftpc->newhost, connectport);
2017
2018   Curl_resolv_unlock(data, addr); /* we're done using this address */
2019
2020   Curl_safefree(conn->secondaryhostname);
2021   conn->secondary_port = ftpc->newport;
2022   conn->secondaryhostname = strdup(ftpc->newhost);
2023   if(!conn->secondaryhostname)
2024     return CURLE_OUT_OF_MEMORY;
2025
2026   conn->bits.do_more = TRUE;
2027   state(data, FTP_STOP); /* this phase is completed */
2028
2029   return result;
2030 }
2031
2032 static CURLcode ftp_state_port_resp(struct Curl_easy *data,
2033                                     int ftpcode)
2034 {
2035   struct connectdata *conn = data->conn;
2036   struct ftp_conn *ftpc = &conn->proto.ftpc;
2037   ftpport fcmd = (ftpport)ftpc->count1;
2038   CURLcode result = CURLE_OK;
2039
2040   /* The FTP spec tells a positive response should have code 200.
2041      Be more permissive here to tolerate deviant servers. */
2042   if(ftpcode / 100 != 2) {
2043     /* the command failed */
2044
2045     if(EPRT == fcmd) {
2046       infof(data, "disabling EPRT usage");
2047       conn->bits.ftp_use_eprt = FALSE;
2048     }
2049     fcmd++;
2050
2051     if(fcmd == DONE) {
2052       failf(data, "Failed to do PORT");
2053       result = CURLE_FTP_PORT_FAILED;
2054     }
2055     else
2056       /* try next */
2057       result = ftp_state_use_port(data, fcmd);
2058   }
2059   else {
2060     infof(data, "Connect data stream actively");
2061     state(data, FTP_STOP); /* end of DO phase */
2062     result = ftp_dophase_done(data, FALSE);
2063   }
2064
2065   return result;
2066 }
2067
2068 static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
2069                                     int ftpcode)
2070 {
2071   CURLcode result = CURLE_OK;
2072   struct FTP *ftp = data->req.p.ftp;
2073   struct connectdata *conn = data->conn;
2074   struct ftp_conn *ftpc = &conn->proto.ftpc;
2075
2076   switch(ftpcode) {
2077   case 213:
2078     {
2079       /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
2080          last .sss part is optional and means fractions of a second */
2081       int year, month, day, hour, minute, second;
2082       if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d",
2083                      &year, &month, &day, &hour, &minute, &second)) {
2084         /* we have a time, reformat it */
2085         char timebuf[24];
2086         msnprintf(timebuf, sizeof(timebuf),
2087                   "%04d%02d%02d %02d:%02d:%02d GMT",
2088                   year, month, day, hour, minute, second);
2089         /* now, convert this into a time() value: */
2090         data->info.filetime = Curl_getdate_capped(timebuf);
2091       }
2092
2093 #ifdef CURL_FTP_HTTPSTYLE_HEAD
2094       /* If we asked for a time of the file and we actually got one as well,
2095          we "emulate" a HTTP-style header in our output. */
2096
2097       if(data->set.opt_no_body &&
2098          ftpc->file &&
2099          data->set.get_filetime &&
2100          (data->info.filetime >= 0) ) {
2101         char headerbuf[128];
2102         int headerbuflen;
2103         time_t filetime = data->info.filetime;
2104         struct tm buffer;
2105         const struct tm *tm = &buffer;
2106
2107         result = Curl_gmtime(filetime, &buffer);
2108         if(result)
2109           return result;
2110
2111         /* format: "Tue, 15 Nov 1994 12:45:26" */
2112         headerbuflen = msnprintf(headerbuf, sizeof(headerbuf),
2113                   "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
2114                   Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
2115                   tm->tm_mday,
2116                   Curl_month[tm->tm_mon],
2117                   tm->tm_year + 1900,
2118                   tm->tm_hour,
2119                   tm->tm_min,
2120                   tm->tm_sec);
2121         result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf,
2122                                    headerbuflen);
2123         if(result)
2124           return result;
2125       } /* end of a ridiculous amount of conditionals */
2126 #endif
2127     }
2128     break;
2129   default:
2130     infof(data, "unsupported MDTM reply format");
2131     break;
2132   case 550: /* 550 is used for several different problems, e.g.
2133                "No such file or directory" or "Permission denied".
2134                It does not mean that the file does not exist at all. */
2135     infof(data, "MDTM failed: file does not exist or permission problem,"
2136           " continuing");
2137     break;
2138   }
2139
2140   if(data->set.timecondition) {
2141     if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
2142       switch(data->set.timecondition) {
2143       case CURL_TIMECOND_IFMODSINCE:
2144       default:
2145         if(data->info.filetime <= data->set.timevalue) {
2146           infof(data, "The requested document is not new enough");
2147           ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
2148           data->info.timecond = TRUE;
2149           state(data, FTP_STOP);
2150           return CURLE_OK;
2151         }
2152         break;
2153       case CURL_TIMECOND_IFUNMODSINCE:
2154         if(data->info.filetime > data->set.timevalue) {
2155           infof(data, "The requested document is not old enough");
2156           ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
2157           data->info.timecond = TRUE;
2158           state(data, FTP_STOP);
2159           return CURLE_OK;
2160         }
2161         break;
2162       } /* switch */
2163     }
2164     else {
2165       infof(data, "Skipping time comparison");
2166     }
2167   }
2168
2169   if(!result)
2170     result = ftp_state_type(data);
2171
2172   return result;
2173 }
2174
2175 static CURLcode ftp_state_type_resp(struct Curl_easy *data,
2176                                     int ftpcode,
2177                                     ftpstate instate)
2178 {
2179   CURLcode result = CURLE_OK;
2180   struct connectdata *conn = data->conn;
2181
2182   if(ftpcode/100 != 2) {
2183     /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
2184        successful 'TYPE I'. While that is not as RFC959 says, it is still a
2185        positive response code and we allow that. */
2186     failf(data, "Couldn't set desired mode");
2187     return CURLE_FTP_COULDNT_SET_TYPE;
2188   }
2189   if(ftpcode != 200)
2190     infof(data, "Got a %03d response code instead of the assumed 200",
2191           ftpcode);
2192
2193   if(instate == FTP_TYPE)
2194     result = ftp_state_size(data, conn);
2195   else if(instate == FTP_LIST_TYPE)
2196     result = ftp_state_list(data);
2197   else if(instate == FTP_RETR_TYPE)
2198     result = ftp_state_retr_prequote(data);
2199   else if(instate == FTP_STOR_TYPE)
2200     result = ftp_state_stor_prequote(data);
2201
2202   return result;
2203 }
2204
2205 static CURLcode ftp_state_retr(struct Curl_easy *data,
2206                                curl_off_t filesize)
2207 {
2208   CURLcode result = CURLE_OK;
2209   struct FTP *ftp = data->req.p.ftp;
2210   struct connectdata *conn = data->conn;
2211   struct ftp_conn *ftpc = &conn->proto.ftpc;
2212
2213   if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
2214     failf(data, "Maximum file size exceeded");
2215     return CURLE_FILESIZE_EXCEEDED;
2216   }
2217   ftp->downloadsize = filesize;
2218
2219   if(data->state.resume_from) {
2220     /* We always (attempt to) get the size of downloads, so it is done before
2221        this even when not doing resumes. */
2222     if(filesize == -1) {
2223       infof(data, "ftp server doesn't support SIZE");
2224       /* We couldn't get the size and therefore we can't know if there really
2225          is a part of the file left to get, although the server will just
2226          close the connection when we start the connection so it won't cause
2227          us any harm, just not make us exit as nicely. */
2228     }
2229     else {
2230       /* We got a file size report, so we check that there actually is a
2231          part of the file left to get, or else we go home.  */
2232       if(data->state.resume_from< 0) {
2233         /* We're supposed to download the last abs(from) bytes */
2234         if(filesize < -data->state.resume_from) {
2235           failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
2236                 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
2237                 data->state.resume_from, filesize);
2238           return CURLE_BAD_DOWNLOAD_RESUME;
2239         }
2240         /* convert to size to download */
2241         ftp->downloadsize = -data->state.resume_from;
2242         /* download from where? */
2243         data->state.resume_from = filesize - ftp->downloadsize;
2244       }
2245       else {
2246         if(filesize < data->state.resume_from) {
2247           failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
2248                 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
2249                 data->state.resume_from, filesize);
2250           return CURLE_BAD_DOWNLOAD_RESUME;
2251         }
2252         /* Now store the number of bytes we are expected to download */
2253         ftp->downloadsize = filesize-data->state.resume_from;
2254       }
2255     }
2256
2257     if(ftp->downloadsize == 0) {
2258       /* no data to transfer */
2259       Curl_setup_transfer(data, -1, -1, FALSE, -1);
2260       infof(data, "File already completely downloaded");
2261
2262       /* Set ->transfer so that we won't get any error in ftp_done()
2263        * because we didn't transfer the any file */
2264       ftp->transfer = PPTRANSFER_NONE;
2265       state(data, FTP_STOP);
2266       return CURLE_OK;
2267     }
2268
2269     /* Set resume file transfer offset */
2270     infof(data, "Instructs server to resume from offset %"
2271           CURL_FORMAT_CURL_OFF_T, data->state.resume_from);
2272
2273     result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
2274                            data->state.resume_from);
2275     if(!result)
2276       state(data, FTP_RETR_REST);
2277   }
2278   else {
2279     /* no resume */
2280     result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
2281     if(!result)
2282       state(data, FTP_RETR);
2283   }
2284
2285   return result;
2286 }
2287
2288 static CURLcode ftp_state_size_resp(struct Curl_easy *data,
2289                                     int ftpcode,
2290                                     ftpstate instate)
2291 {
2292   CURLcode result = CURLE_OK;
2293   curl_off_t filesize = -1;
2294   char *buf = data->state.buffer;
2295
2296   /* get the size from the ascii string: */
2297   if(ftpcode == 213) {
2298     /* To allow servers to prepend "rubbish" in the response string, we scan
2299        for all the digits at the end of the response and parse only those as a
2300        number. */
2301     char *start = &buf[4];
2302     char *fdigit = strchr(start, '\r');
2303     if(fdigit) {
2304       do
2305         fdigit--;
2306       while(ISDIGIT(*fdigit) && (fdigit > start));
2307       if(!ISDIGIT(*fdigit))
2308         fdigit++;
2309     }
2310     else
2311       fdigit = start;
2312     /* ignores parsing errors, which will make the size remain unknown */
2313     (void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
2314
2315   }
2316   else if(ftpcode == 550) { /* "No such file or directory" */
2317     /* allow a SIZE failure for (resumed) uploads, when probing what command
2318        to use */
2319     if(instate != FTP_STOR_SIZE) {
2320       failf(data, "The file does not exist");
2321       return CURLE_REMOTE_FILE_NOT_FOUND;
2322     }
2323   }
2324
2325   if(instate == FTP_SIZE) {
2326 #ifdef CURL_FTP_HTTPSTYLE_HEAD
2327     if(-1 != filesize) {
2328       char clbuf[128];
2329       int clbuflen = msnprintf(clbuf, sizeof(clbuf),
2330                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
2331       result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen);
2332       if(result)
2333         return result;
2334     }
2335 #endif
2336     Curl_pgrsSetDownloadSize(data, filesize);
2337     result = ftp_state_rest(data, data->conn);
2338   }
2339   else if(instate == FTP_RETR_SIZE) {
2340     Curl_pgrsSetDownloadSize(data, filesize);
2341     result = ftp_state_retr(data, filesize);
2342   }
2343   else if(instate == FTP_STOR_SIZE) {
2344     data->state.resume_from = filesize;
2345     result = ftp_state_ul_setup(data, TRUE);
2346   }
2347
2348   return result;
2349 }
2350
2351 static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
2352                                     struct connectdata *conn,
2353                                     int ftpcode,
2354                                     ftpstate instate)
2355 {
2356   CURLcode result = CURLE_OK;
2357   struct ftp_conn *ftpc = &conn->proto.ftpc;
2358
2359   switch(instate) {
2360   case FTP_REST:
2361   default:
2362 #ifdef CURL_FTP_HTTPSTYLE_HEAD
2363     if(ftpcode == 350) {
2364       char buffer[24]= { "Accept-ranges: bytes\r\n" };
2365       result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer,
2366                                  strlen(buffer));
2367       if(result)
2368         return result;
2369     }
2370 #endif
2371     result = ftp_state_prepare_transfer(data);
2372     break;
2373
2374   case FTP_RETR_REST:
2375     if(ftpcode != 350) {
2376       failf(data, "Couldn't use REST");
2377       result = CURLE_FTP_COULDNT_USE_REST;
2378     }
2379     else {
2380       result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
2381       if(!result)
2382         state(data, FTP_RETR);
2383     }
2384     break;
2385   }
2386
2387   return result;
2388 }
2389
2390 static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
2391                                     int ftpcode, ftpstate instate)
2392 {
2393   CURLcode result = CURLE_OK;
2394   struct connectdata *conn = data->conn;
2395
2396   if(ftpcode >= 400) {
2397     failf(data, "Failed FTP upload: %0d", ftpcode);
2398     state(data, FTP_STOP);
2399     /* oops, we never close the sockets! */
2400     return CURLE_UPLOAD_FAILED;
2401   }
2402
2403   conn->proto.ftpc.state_saved = instate;
2404
2405   /* PORT means we are now awaiting the server to connect to us. */
2406   if(data->set.ftp_use_port) {
2407     bool connected;
2408
2409     state(data, FTP_STOP); /* no longer in STOR state */
2410
2411     result = AllowServerConnect(data, &connected);
2412     if(result)
2413       return result;
2414
2415     if(!connected) {
2416       struct ftp_conn *ftpc = &conn->proto.ftpc;
2417       infof(data, "Data conn was not available immediately");
2418       ftpc->wait_data_conn = TRUE;
2419     }
2420
2421     return CURLE_OK;
2422   }
2423   return InitiateTransfer(data);
2424 }
2425
2426 /* for LIST and RETR responses */
2427 static CURLcode ftp_state_get_resp(struct Curl_easy *data,
2428                                    int ftpcode,
2429                                    ftpstate instate)
2430 {
2431   CURLcode result = CURLE_OK;
2432   struct FTP *ftp = data->req.p.ftp;
2433   struct connectdata *conn = data->conn;
2434
2435   if((ftpcode == 150) || (ftpcode == 125)) {
2436
2437     /*
2438       A;
2439       150 Opening BINARY mode data connection for /etc/passwd (2241
2440       bytes).  (ok, the file is being transferred)
2441
2442       B:
2443       150 Opening ASCII mode data connection for /bin/ls
2444
2445       C:
2446       150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes).
2447
2448       D:
2449       150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes)
2450
2451       E:
2452       125 Data connection already open; Transfer starting. */
2453
2454     curl_off_t size = -1; /* default unknown size */
2455
2456
2457     /*
2458      * It appears that there are FTP-servers that return size 0 for files when
2459      * SIZE is used on the file while being in BINARY mode. To work around
2460      * that (stupid) behavior, we attempt to parse the RETR response even if
2461      * the SIZE returned size zero.
2462      *
2463      * Debugging help from Salvatore Sorrentino on February 26, 2003.
2464      */
2465
2466     if((instate != FTP_LIST) &&
2467        !data->state.prefer_ascii &&
2468        (ftp->downloadsize < 1)) {
2469       /*
2470        * It seems directory listings either don't show the size or very
2471        * often uses size 0 anyway. ASCII transfers may very well turn out
2472        * that the transferred amount of data is not the same as this line
2473        * tells, why using this number in those cases only confuses us.
2474        *
2475        * Example D above makes this parsing a little tricky */
2476       char *bytes;
2477       char *buf = data->state.buffer;
2478       bytes = strstr(buf, " bytes");
2479       if(bytes) {
2480         long in = (long)(--bytes-buf);
2481         /* this is a hint there is size information in there! ;-) */
2482         while(--in) {
2483           /* scan for the left parenthesis and break there */
2484           if('(' == *bytes)
2485             break;
2486           /* skip only digits */
2487           if(!ISDIGIT(*bytes)) {
2488             bytes = NULL;
2489             break;
2490           }
2491           /* one more estep backwards */
2492           bytes--;
2493         }
2494         /* if we have nothing but digits: */
2495         if(bytes) {
2496           ++bytes;
2497           /* get the number! */
2498           (void)curlx_strtoofft(bytes, NULL, 0, &size);
2499         }
2500       }
2501     }
2502     else if(ftp->downloadsize > -1)
2503       size = ftp->downloadsize;
2504
2505     if(size > data->req.maxdownload && data->req.maxdownload > 0)
2506       size = data->req.size = data->req.maxdownload;
2507     else if((instate != FTP_LIST) && (data->state.prefer_ascii))
2508       size = -1; /* kludge for servers that understate ASCII mode file size */
2509
2510     infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T,
2511           data->req.maxdownload);
2512
2513     if(instate != FTP_LIST)
2514       infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T,
2515             size);
2516
2517     /* FTP download: */
2518     conn->proto.ftpc.state_saved = instate;
2519     conn->proto.ftpc.retr_size_saved = size;
2520
2521     if(data->set.ftp_use_port) {
2522       bool connected;
2523
2524       result = AllowServerConnect(data, &connected);
2525       if(result)
2526         return result;
2527
2528       if(!connected) {
2529         struct ftp_conn *ftpc = &conn->proto.ftpc;
2530         infof(data, "Data conn was not available immediately");
2531         state(data, FTP_STOP);
2532         ftpc->wait_data_conn = TRUE;
2533       }
2534     }
2535     else
2536       return InitiateTransfer(data);
2537   }
2538   else {
2539     if((instate == FTP_LIST) && (ftpcode == 450)) {
2540       /* simply no matching files in the dir listing */
2541       ftp->transfer = PPTRANSFER_NONE; /* don't download anything */
2542       state(data, FTP_STOP); /* this phase is over */
2543     }
2544     else {
2545       failf(data, "RETR response: %03d", ftpcode);
2546       return instate == FTP_RETR && ftpcode == 550?
2547         CURLE_REMOTE_FILE_NOT_FOUND:
2548         CURLE_FTP_COULDNT_RETR_FILE;
2549     }
2550   }
2551
2552   return result;
2553 }
2554
2555 /* after USER, PASS and ACCT */
2556 static CURLcode ftp_state_loggedin(struct Curl_easy *data)
2557 {
2558   CURLcode result = CURLE_OK;
2559   struct connectdata *conn = data->conn;
2560
2561   if(conn->bits.ftp_use_control_ssl) {
2562     /* PBSZ = PROTECTION BUFFER SIZE.
2563
2564     The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
2565
2566     Specifically, the PROT command MUST be preceded by a PBSZ
2567     command and a PBSZ command MUST be preceded by a successful
2568     security data exchange (the TLS negotiation in this case)
2569
2570     ... (and on page 8):
2571
2572     Thus the PBSZ command must still be issued, but must have a
2573     parameter of '0' to indicate that no buffering is taking place
2574     and the data connection should not be encapsulated.
2575     */
2576     result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
2577     if(!result)
2578       state(data, FTP_PBSZ);
2579   }
2580   else {
2581     result = ftp_state_pwd(data, conn);
2582   }
2583   return result;
2584 }
2585
2586 /* for USER and PASS responses */
2587 static CURLcode ftp_state_user_resp(struct Curl_easy *data,
2588                                     int ftpcode,
2589                                     ftpstate instate)
2590 {
2591   CURLcode result = CURLE_OK;
2592   struct connectdata *conn = data->conn;
2593   struct ftp_conn *ftpc = &conn->proto.ftpc;
2594   (void)instate; /* no use for this yet */
2595
2596   /* some need password anyway, and others just return 2xx ignored */
2597   if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
2598     /* 331 Password required for ...
2599        (the server requires to send the user's password too) */
2600     result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
2601                            conn->passwd?conn->passwd:"");
2602     if(!result)
2603       state(data, FTP_PASS);
2604   }
2605   else if(ftpcode/100 == 2) {
2606     /* 230 User ... logged in.
2607        (the user logged in with or without password) */
2608     result = ftp_state_loggedin(data);
2609   }
2610   else if(ftpcode == 332) {
2611     if(data->set.str[STRING_FTP_ACCOUNT]) {
2612       result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
2613                              data->set.str[STRING_FTP_ACCOUNT]);
2614       if(!result)
2615         state(data, FTP_ACCT);
2616     }
2617     else {
2618       failf(data, "ACCT requested but none available");
2619       result = CURLE_LOGIN_DENIED;
2620     }
2621   }
2622   else {
2623     /* All other response codes, like:
2624
2625     530 User ... access denied
2626     (the server denies to log the specified user) */
2627
2628     if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
2629        !ftpc->ftp_trying_alternative) {
2630       /* Ok, USER failed.  Let's try the supplied command. */
2631       result =
2632         Curl_pp_sendf(data, &ftpc->pp, "%s",
2633                       data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
2634       if(!result) {
2635         ftpc->ftp_trying_alternative = TRUE;
2636         state(data, FTP_USER);
2637       }
2638     }
2639     else {
2640       failf(data, "Access denied: %03d", ftpcode);
2641       result = CURLE_LOGIN_DENIED;
2642     }
2643   }
2644   return result;
2645 }
2646
2647 /* for ACCT response */
2648 static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
2649                                     int ftpcode)
2650 {
2651   CURLcode result = CURLE_OK;
2652   if(ftpcode != 230) {
2653     failf(data, "ACCT rejected by server: %03d", ftpcode);
2654     result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
2655   }
2656   else
2657     result = ftp_state_loggedin(data);
2658
2659   return result;
2660 }
2661
2662
2663 static CURLcode ftp_statemachine(struct Curl_easy *data,
2664                                  struct connectdata *conn)
2665 {
2666   CURLcode result;
2667   curl_socket_t sock = conn->sock[FIRSTSOCKET];
2668   int ftpcode;
2669   struct ftp_conn *ftpc = &conn->proto.ftpc;
2670   struct pingpong *pp = &ftpc->pp;
2671   static const char ftpauth[][4]  = { "SSL", "TLS" };
2672   size_t nread = 0;
2673
2674   if(pp->sendleft)
2675     return Curl_pp_flushsend(data, pp);
2676
2677   result = ftp_readresp(data, sock, pp, &ftpcode, &nread);
2678   if(result)
2679     return result;
2680
2681   if(ftpcode) {
2682     /* we have now received a full FTP server response */
2683     switch(ftpc->state) {
2684     case FTP_WAIT220:
2685       if(ftpcode == 230) {
2686         /* 230 User logged in - already! Take as 220 if TLS required. */
2687         if(data->set.use_ssl <= CURLUSESSL_TRY ||
2688            conn->bits.ftp_use_control_ssl)
2689           return ftp_state_user_resp(data, ftpcode, ftpc->state);
2690       }
2691       else if(ftpcode != 220) {
2692         failf(data, "Got a %03d ftp-server response when 220 was expected",
2693               ftpcode);
2694         return CURLE_WEIRD_SERVER_REPLY;
2695       }
2696
2697       /* We have received a 220 response fine, now we proceed. */
2698 #ifdef HAVE_GSSAPI
2699       if(data->set.krb) {
2700         /* If not anonymous login, try a secure login. Note that this
2701            procedure is still BLOCKING. */
2702
2703         Curl_sec_request_prot(conn, "private");
2704         /* We set private first as default, in case the line below fails to
2705            set a valid level */
2706         Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
2707
2708         if(Curl_sec_login(data, conn)) {
2709           failf(data, "secure login failed");
2710           return CURLE_WEIRD_SERVER_REPLY;
2711         }
2712         infof(data, "Authentication successful");
2713       }
2714 #endif
2715
2716       if(data->set.use_ssl && !conn->bits.ftp_use_control_ssl) {
2717         /* We don't have a SSL/TLS control connection yet, but FTPS is
2718            requested. Try a FTPS connection now */
2719
2720         ftpc->count3 = 0;
2721         switch(data->set.ftpsslauth) {
2722         case CURLFTPAUTH_DEFAULT:
2723         case CURLFTPAUTH_SSL:
2724           ftpc->count2 = 1; /* add one to get next */
2725           ftpc->count1 = 0;
2726           break;
2727         case CURLFTPAUTH_TLS:
2728           ftpc->count2 = -1; /* subtract one to get next */
2729           ftpc->count1 = 1;
2730           break;
2731         default:
2732           failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d",
2733                 (int)data->set.ftpsslauth);
2734           return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
2735         }
2736         result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
2737                                ftpauth[ftpc->count1]);
2738         if(!result)
2739           state(data, FTP_AUTH);
2740       }
2741       else
2742         result = ftp_state_user(data, conn);
2743       break;
2744
2745     case FTP_AUTH:
2746       /* we have gotten the response to a previous AUTH command */
2747
2748       if(pp->cache_size)
2749         return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
2750
2751       /* RFC2228 (page 5) says:
2752        *
2753        * If the server is willing to accept the named security mechanism,
2754        * and does not require any security data, it must respond with
2755        * reply code 234/334.
2756        */
2757
2758       if((ftpcode == 234) || (ftpcode == 334)) {
2759         /* Curl_ssl_connect is BLOCKING */
2760         result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
2761         if(!result) {
2762           conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
2763           conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
2764           result = ftp_state_user(data, conn);
2765         }
2766       }
2767       else if(ftpc->count3 < 1) {
2768         ftpc->count3++;
2769         ftpc->count1 += ftpc->count2; /* get next attempt */
2770         result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
2771                                ftpauth[ftpc->count1]);
2772         /* remain in this same state */
2773       }
2774       else {
2775         if(data->set.use_ssl > CURLUSESSL_TRY)
2776           /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */
2777           result = CURLE_USE_SSL_FAILED;
2778         else
2779           /* ignore the failure and continue */
2780           result = ftp_state_user(data, conn);
2781       }
2782       break;
2783
2784     case FTP_USER:
2785     case FTP_PASS:
2786       result = ftp_state_user_resp(data, ftpcode, ftpc->state);
2787       break;
2788
2789     case FTP_ACCT:
2790       result = ftp_state_acct_resp(data, ftpcode);
2791       break;
2792
2793     case FTP_PBSZ:
2794       result =
2795         Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
2796                       data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
2797       if(!result)
2798         state(data, FTP_PROT);
2799       break;
2800
2801     case FTP_PROT:
2802       if(ftpcode/100 == 2)
2803         /* We have enabled SSL for the data connection! */
2804         conn->bits.ftp_use_data_ssl =
2805           (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
2806       /* FTP servers typically responds with 500 if they decide to reject
2807          our 'P' request */
2808       else if(data->set.use_ssl > CURLUSESSL_CONTROL)
2809         /* we failed and bails out */
2810         return CURLE_USE_SSL_FAILED;
2811
2812       if(data->set.ftp_ccc) {
2813         /* CCC - Clear Command Channel
2814          */
2815         result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
2816         if(!result)
2817           state(data, FTP_CCC);
2818       }
2819       else
2820         result = ftp_state_pwd(data, conn);
2821       break;
2822
2823     case FTP_CCC:
2824       if(ftpcode < 500) {
2825         /* First shut down the SSL layer (note: this call will block) */
2826         result = Curl_ssl_shutdown(data, conn, FIRSTSOCKET);
2827
2828         if(result)
2829           failf(data, "Failed to clear the command channel (CCC)");
2830       }
2831       if(!result)
2832         /* Then continue as normal */
2833         result = ftp_state_pwd(data, conn);
2834       break;
2835
2836     case FTP_PWD:
2837       if(ftpcode == 257) {
2838         char *ptr = &data->state.buffer[4];  /* start on the first letter */
2839         const size_t buf_size = data->set.buffer_size;
2840         char *dir;
2841         bool entry_extracted = FALSE;
2842
2843         dir = malloc(nread + 1);
2844         if(!dir)
2845           return CURLE_OUT_OF_MEMORY;
2846
2847         /* Reply format is like
2848            257<space>[rubbish]"<directory-name>"<space><commentary> and the
2849            RFC959 says
2850
2851            The directory name can contain any character; embedded
2852            double-quotes should be escaped by double-quotes (the
2853            "quote-doubling" convention).
2854         */
2855
2856         /* scan for the first double-quote for non-standard responses */
2857         while(ptr < &data->state.buffer[buf_size]
2858               && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
2859           ptr++;
2860
2861         if('\"' == *ptr) {
2862           /* it started good */
2863           char *store;
2864           ptr++;
2865           for(store = dir; *ptr;) {
2866             if('\"' == *ptr) {
2867               if('\"' == ptr[1]) {
2868                 /* "quote-doubling" */
2869                 *store = ptr[1];
2870                 ptr++;
2871               }
2872               else {
2873                 /* end of path */
2874                 entry_extracted = TRUE;
2875                 break; /* get out of this loop */
2876               }
2877             }
2878             else
2879               *store = *ptr;
2880             store++;
2881             ptr++;
2882           }
2883           *store = '\0'; /* null-terminate */
2884         }
2885         if(entry_extracted) {
2886           /* If the path name does not look like an absolute path (i.e.: it
2887              does not start with a '/'), we probably need some server-dependent
2888              adjustments. For example, this is the case when connecting to
2889              an OS400 FTP server: this server supports two name syntaxes,
2890              the default one being incompatible with standard paths. In
2891              addition, this server switches automatically to the regular path
2892              syntax when one is encountered in a command: this results in
2893              having an entrypath in the wrong syntax when later used in CWD.
2894                The method used here is to check the server OS: we do it only
2895              if the path name looks strange to minimize overhead on other
2896              systems. */
2897
2898           if(!ftpc->server_os && dir[0] != '/') {
2899             result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
2900             if(result) {
2901               free(dir);
2902               return result;
2903             }
2904             Curl_safefree(ftpc->entrypath);
2905             ftpc->entrypath = dir; /* remember this */
2906             infof(data, "Entry path is '%s'", ftpc->entrypath);
2907             /* also save it where getinfo can access it: */
2908             data->state.most_recent_ftp_entrypath = ftpc->entrypath;
2909             state(data, FTP_SYST);
2910             break;
2911           }
2912
2913           Curl_safefree(ftpc->entrypath);
2914           ftpc->entrypath = dir; /* remember this */
2915           infof(data, "Entry path is '%s'", ftpc->entrypath);
2916           /* also save it where getinfo can access it: */
2917           data->state.most_recent_ftp_entrypath = ftpc->entrypath;
2918         }
2919         else {
2920           /* couldn't get the path */
2921           free(dir);
2922           infof(data, "Failed to figure out path");
2923         }
2924       }
2925       state(data, FTP_STOP); /* we are done with the CONNECT phase! */
2926       DEBUGF(infof(data, "protocol connect phase DONE"));
2927       break;
2928
2929     case FTP_SYST:
2930       if(ftpcode == 215) {
2931         char *ptr = &data->state.buffer[4];  /* start on the first letter */
2932         char *os;
2933         char *store;
2934
2935         os = malloc(nread + 1);
2936         if(!os)
2937           return CURLE_OUT_OF_MEMORY;
2938
2939         /* Reply format is like
2940            215<space><OS-name><space><commentary>
2941         */
2942         while(*ptr == ' ')
2943           ptr++;
2944         for(store = os; *ptr && *ptr != ' ';)
2945           *store++ = *ptr++;
2946         *store = '\0'; /* null-terminate */
2947
2948         /* Check for special servers here. */
2949
2950         if(strcasecompare(os, "OS/400")) {
2951           /* Force OS400 name format 1. */
2952           result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1");
2953           if(result) {
2954             free(os);
2955             return result;
2956           }
2957           /* remember target server OS */
2958           Curl_safefree(ftpc->server_os);
2959           ftpc->server_os = os;
2960           state(data, FTP_NAMEFMT);
2961           break;
2962         }
2963         /* Nothing special for the target server. */
2964         /* remember target server OS */
2965         Curl_safefree(ftpc->server_os);
2966         ftpc->server_os = os;
2967       }
2968       else {
2969         /* Cannot identify server OS. Continue anyway and cross fingers. */
2970       }
2971
2972       state(data, FTP_STOP); /* we are done with the CONNECT phase! */
2973       DEBUGF(infof(data, "protocol connect phase DONE"));
2974       break;
2975
2976     case FTP_NAMEFMT:
2977       if(ftpcode == 250) {
2978         /* Name format change successful: reload initial path. */
2979         ftp_state_pwd(data, conn);
2980         break;
2981       }
2982
2983       state(data, FTP_STOP); /* we are done with the CONNECT phase! */
2984       DEBUGF(infof(data, "protocol connect phase DONE"));
2985       break;
2986
2987     case FTP_QUOTE:
2988     case FTP_POSTQUOTE:
2989     case FTP_RETR_PREQUOTE:
2990     case FTP_STOR_PREQUOTE:
2991       if((ftpcode >= 400) && !ftpc->count2) {
2992         /* failure response code, and not allowed to fail */
2993         failf(data, "QUOT command failed with %03d", ftpcode);
2994         result = CURLE_QUOTE_ERROR;
2995       }
2996       else
2997         result = ftp_state_quote(data, FALSE, ftpc->state);
2998       break;
2999
3000     case FTP_CWD:
3001       if(ftpcode/100 != 2) {
3002         /* failure to CWD there */
3003         if(data->set.ftp_create_missing_dirs &&
3004            ftpc->cwdcount && !ftpc->count2) {
3005           /* try making it */
3006           ftpc->count2++; /* counter to prevent CWD-MKD loops */
3007
3008           /* count3 is set to allow MKD to fail once per dir. In the case when
3009           CWD fails and then MKD fails (due to another session raced it to
3010           create the dir) this then allows for a second try to CWD to it. */
3011           ftpc->count3 = (data->set.ftp_create_missing_dirs == 2) ? 1 : 0;
3012
3013           result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s",
3014                                  ftpc->dirs[ftpc->cwdcount - 1]);
3015           if(!result)
3016             state(data, FTP_MKD);
3017         }
3018         else {
3019           /* return failure */
3020           failf(data, "Server denied you to change to the given directory");
3021           ftpc->cwdfail = TRUE; /* don't remember this path as we failed
3022                                    to enter it */
3023           result = CURLE_REMOTE_ACCESS_DENIED;
3024         }
3025       }
3026       else {
3027         /* success */
3028         ftpc->count2 = 0;
3029         if(++ftpc->cwdcount <= ftpc->dirdepth)
3030           /* send next CWD */
3031           result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
3032                                  ftpc->dirs[ftpc->cwdcount - 1]);
3033         else
3034           result = ftp_state_mdtm(data);
3035       }
3036       break;
3037
3038     case FTP_MKD:
3039       if((ftpcode/100 != 2) && !ftpc->count3--) {
3040         /* failure to MKD the dir */
3041         failf(data, "Failed to MKD dir: %03d", ftpcode);
3042         result = CURLE_REMOTE_ACCESS_DENIED;
3043       }
3044       else {
3045         state(data, FTP_CWD);
3046         /* send CWD */
3047         result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
3048                                ftpc->dirs[ftpc->cwdcount - 1]);
3049       }
3050       break;
3051
3052     case FTP_MDTM:
3053       result = ftp_state_mdtm_resp(data, ftpcode);
3054       break;
3055
3056     case FTP_TYPE:
3057     case FTP_LIST_TYPE:
3058     case FTP_RETR_TYPE:
3059     case FTP_STOR_TYPE:
3060       result = ftp_state_type_resp(data, ftpcode, ftpc->state);
3061       break;
3062
3063     case FTP_SIZE:
3064     case FTP_RETR_SIZE:
3065     case FTP_STOR_SIZE:
3066       result = ftp_state_size_resp(data, ftpcode, ftpc->state);
3067       break;
3068
3069     case FTP_REST:
3070     case FTP_RETR_REST:
3071       result = ftp_state_rest_resp(data, conn, ftpcode, ftpc->state);
3072       break;
3073
3074     case FTP_PRET:
3075       if(ftpcode != 200) {
3076         /* there only is this one standard OK return code. */
3077         failf(data, "PRET command not accepted: %03d", ftpcode);
3078         return CURLE_FTP_PRET_FAILED;
3079       }
3080       result = ftp_state_use_pasv(data, conn);
3081       break;
3082
3083     case FTP_PASV:
3084       result = ftp_state_pasv_resp(data, ftpcode);
3085       break;
3086
3087     case FTP_PORT:
3088       result = ftp_state_port_resp(data, ftpcode);
3089       break;
3090
3091     case FTP_LIST:
3092     case FTP_RETR:
3093       result = ftp_state_get_resp(data, ftpcode, ftpc->state);
3094       break;
3095
3096     case FTP_STOR:
3097       result = ftp_state_stor_resp(data, ftpcode, ftpc->state);
3098       break;
3099
3100     case FTP_QUIT:
3101       /* fallthrough, just stop! */
3102     default:
3103       /* internal error */
3104       state(data, FTP_STOP);
3105       break;
3106     }
3107   } /* if(ftpcode) */
3108
3109   return result;
3110 }
3111
3112
3113 /* called repeatedly until done from multi.c */
3114 static CURLcode ftp_multi_statemach(struct Curl_easy *data,
3115                                     bool *done)
3116 {
3117   struct connectdata *conn = data->conn;
3118   struct ftp_conn *ftpc = &conn->proto.ftpc;
3119   CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE);
3120
3121   /* Check for the state outside of the Curl_socket_check() return code checks
3122      since at times we are in fact already in this state when this function
3123      gets called. */
3124   *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
3125
3126   return result;
3127 }
3128
3129 static CURLcode ftp_block_statemach(struct Curl_easy *data,
3130                                     struct connectdata *conn)
3131 {
3132   struct ftp_conn *ftpc = &conn->proto.ftpc;
3133   struct pingpong *pp = &ftpc->pp;
3134   CURLcode result = CURLE_OK;
3135
3136   while(ftpc->state != FTP_STOP) {
3137     result = Curl_pp_statemach(data, pp, TRUE, TRUE /* disconnecting */);
3138     if(result)
3139       break;
3140   }
3141
3142   return result;
3143 }
3144
3145 /*
3146  * ftp_connect() should do everything that is to be considered a part of
3147  * the connection phase.
3148  *
3149  * The variable 'done' points to will be TRUE if the protocol-layer connect
3150  * phase is done when this function returns, or FALSE if not.
3151  *
3152  */
3153 static CURLcode ftp_connect(struct Curl_easy *data,
3154                             bool *done) /* see description above */
3155 {
3156   CURLcode result;
3157   struct connectdata *conn = data->conn;
3158   struct ftp_conn *ftpc = &conn->proto.ftpc;
3159   struct pingpong *pp = &ftpc->pp;
3160
3161   *done = FALSE; /* default to not done yet */
3162
3163   /* We always support persistent connections on ftp */
3164   connkeep(conn, "FTP default");
3165
3166   PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp);
3167
3168   if(conn->handler->flags & PROTOPT_SSL) {
3169     /* BLOCKING */
3170     result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
3171     if(result)
3172       return result;
3173     conn->bits.ftp_use_control_ssl = TRUE;
3174   }
3175
3176   Curl_pp_setup(pp); /* once per transfer */
3177   Curl_pp_init(data, pp); /* init the generic pingpong data */
3178
3179   /* When we connect, we start in the state where we await the 220
3180      response */
3181   state(data, FTP_WAIT220);
3182
3183   result = ftp_multi_statemach(data, done);
3184
3185   return result;
3186 }
3187
3188 /***********************************************************************
3189  *
3190  * ftp_done()
3191  *
3192  * The DONE function. This does what needs to be done after a single DO has
3193  * performed.
3194  *
3195  * Input argument is already checked for validity.
3196  */
3197 static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
3198                          bool premature)
3199 {
3200   struct connectdata *conn = data->conn;
3201   struct FTP *ftp = data->req.p.ftp;
3202   struct ftp_conn *ftpc = &conn->proto.ftpc;
3203   struct pingpong *pp = &ftpc->pp;
3204   ssize_t nread;
3205   int ftpcode;
3206   CURLcode result = CURLE_OK;
3207   char *rawPath = NULL;
3208   size_t pathLen = 0;
3209
3210   if(!ftp)
3211     return CURLE_OK;
3212
3213   switch(status) {
3214   case CURLE_BAD_DOWNLOAD_RESUME:
3215   case CURLE_FTP_WEIRD_PASV_REPLY:
3216   case CURLE_FTP_PORT_FAILED:
3217   case CURLE_FTP_ACCEPT_FAILED:
3218   case CURLE_FTP_ACCEPT_TIMEOUT:
3219   case CURLE_FTP_COULDNT_SET_TYPE:
3220   case CURLE_FTP_COULDNT_RETR_FILE:
3221   case CURLE_PARTIAL_FILE:
3222   case CURLE_UPLOAD_FAILED:
3223   case CURLE_REMOTE_ACCESS_DENIED:
3224   case CURLE_FILESIZE_EXCEEDED:
3225   case CURLE_REMOTE_FILE_NOT_FOUND:
3226   case CURLE_WRITE_ERROR:
3227     /* the connection stays alive fine even though this happened */
3228     /* fall-through */
3229   case CURLE_OK: /* doesn't affect the control connection's status */
3230     if(!premature)
3231       break;
3232
3233     /* until we cope better with prematurely ended requests, let them
3234      * fallback as if in complete failure */
3235     /* FALLTHROUGH */
3236   default:       /* by default, an error means the control connection is
3237                     wedged and should not be used anymore */
3238     ftpc->ctl_valid = FALSE;
3239     ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the
3240                              current path, as this connection is going */
3241     connclose(conn, "FTP ended with bad error code");
3242     result = status;      /* use the already set error code */
3243     break;
3244   }
3245
3246   if(data->state.wildcardmatch) {
3247     if(data->set.chunk_end && ftpc->file) {
3248       Curl_set_in_callback(data, true);
3249       data->set.chunk_end(data->wildcard.customptr);
3250       Curl_set_in_callback(data, false);
3251     }
3252     ftpc->known_filesize = -1;
3253   }
3254
3255   if(!result)
3256     /* get the url-decoded "raw" path */
3257     result = Curl_urldecode(ftp->path, 0, &rawPath, &pathLen,
3258                             REJECT_CTRL);
3259   if(result) {
3260     /* We can limp along anyway (and should try to since we may already be in
3261      * the error path) */
3262     ftpc->ctl_valid = FALSE; /* mark control connection as bad */
3263     connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
3264     free(ftpc->prevpath);
3265     ftpc->prevpath = NULL; /* no path remembering */
3266   }
3267   else { /* remember working directory for connection reuse */
3268     if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
3269       free(rawPath); /* full path => no CWDs happened => keep ftpc->prevpath */
3270     else {
3271       free(ftpc->prevpath);
3272
3273       if(!ftpc->cwdfail) {
3274         if(data->set.ftp_filemethod == FTPFILE_NOCWD)
3275           pathLen = 0; /* relative path => working directory is FTP home */
3276         else
3277           pathLen -= ftpc->file?strlen(ftpc->file):0; /* file is url-decoded */
3278
3279         rawPath[pathLen] = '\0';
3280         ftpc->prevpath = rawPath;
3281       }
3282       else {
3283         free(rawPath);
3284         ftpc->prevpath = NULL; /* no path */
3285       }
3286     }
3287
3288     if(ftpc->prevpath)
3289       infof(data, "Remembering we are in dir \"%s\"", ftpc->prevpath);
3290   }
3291
3292   /* free the dir tree and file parts */
3293   freedirs(ftpc);
3294
3295   /* shut down the socket to inform the server we're done */
3296
3297 #ifdef _WIN32_WCE
3298   shutdown(conn->sock[SECONDARYSOCKET], 2);  /* SD_BOTH */
3299 #endif
3300
3301   if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
3302     if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
3303       /* partial download completed */
3304       result = Curl_pp_sendf(data, pp, "%s", "ABOR");
3305       if(result) {
3306         failf(data, "Failure sending ABOR command: %s",
3307               curl_easy_strerror(result));
3308         ftpc->ctl_valid = FALSE; /* mark control connection as bad */
3309         connclose(conn, "ABOR command failed"); /* connection closure */
3310       }
3311     }
3312
3313     if(conn->ssl[SECONDARYSOCKET].use) {
3314       /* The secondary socket is using SSL so we must close down that part
3315          first before we close the socket for real */
3316       Curl_ssl_close(data, conn, SECONDARYSOCKET);
3317
3318       /* Note that we keep "use" set to TRUE since that (next) connection is
3319          still requested to use SSL */
3320     }
3321     close_secondarysocket(data, conn);
3322   }
3323
3324   if(!result && (ftp->transfer == PPTRANSFER_BODY) && ftpc->ctl_valid &&
3325      pp->pending_resp && !premature) {
3326     /*
3327      * Let's see what the server says about the transfer we just performed,
3328      * but lower the timeout as sometimes this connection has died while the
3329      * data has been transferred. This happens when doing through NATs etc that
3330      * abandon old silent connections.
3331      */
3332     timediff_t old_time = pp->response_time;
3333
3334     pp->response_time = 60*1000; /* give it only a minute for now */
3335     pp->response = Curl_now(); /* timeout relative now */
3336
3337     result = Curl_GetFTPResponse(data, &nread, &ftpcode);
3338
3339     pp->response_time = old_time; /* set this back to previous value */
3340
3341     if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
3342       failf(data, "control connection looks dead");
3343       ftpc->ctl_valid = FALSE; /* mark control connection as bad */
3344       connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
3345     }
3346
3347     if(result) {
3348       Curl_safefree(ftp->pathalloc);
3349       return result;
3350     }
3351
3352     if(ftpc->dont_check && data->req.maxdownload > 0) {
3353       /* we have just sent ABOR and there is no reliable way to check if it was
3354        * successful or not; we have to close the connection now */
3355       infof(data, "partial download completed, closing connection");
3356       connclose(conn, "Partial download with no ability to check");
3357       return result;
3358     }
3359
3360     if(!ftpc->dont_check) {
3361       /* 226 Transfer complete, 250 Requested file action okay, completed. */
3362       switch(ftpcode) {
3363       case 226:
3364       case 250:
3365         break;
3366       case 552:
3367         failf(data, "Exceeded storage allocation");
3368         result = CURLE_REMOTE_DISK_FULL;
3369         break;
3370       default:
3371         failf(data, "server did not report OK, got %d", ftpcode);
3372         result = CURLE_PARTIAL_FILE;
3373         break;
3374       }
3375     }
3376   }
3377
3378   if(result || premature)
3379     /* the response code from the transfer showed an error already so no
3380        use checking further */
3381     ;
3382   else if(data->set.upload) {
3383     if((-1 != data->state.infilesize) &&
3384        (data->state.infilesize != data->req.writebytecount) &&
3385        !data->set.crlf &&
3386        (ftp->transfer == PPTRANSFER_BODY)) {
3387       failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
3388             " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
3389             data->req.writebytecount, data->state.infilesize);
3390       result = CURLE_PARTIAL_FILE;
3391     }
3392   }
3393   else {
3394     if((-1 != data->req.size) &&
3395        (data->req.size != data->req.bytecount) &&
3396 #ifdef CURL_DO_LINEEND_CONV
3397        /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
3398         * we'll check to see if the discrepancy can be explained by the number
3399         * of CRLFs we've changed to LFs.
3400         */
3401        ((data->req.size + data->state.crlf_conversions) !=
3402         data->req.bytecount) &&
3403 #endif /* CURL_DO_LINEEND_CONV */
3404        (data->req.maxdownload != data->req.bytecount)) {
3405       failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
3406             " bytes", data->req.bytecount);
3407       result = CURLE_PARTIAL_FILE;
3408     }
3409     else if(!ftpc->dont_check &&
3410             !data->req.bytecount &&
3411             (data->req.size>0)) {
3412       failf(data, "No data was received");
3413       result = CURLE_FTP_COULDNT_RETR_FILE;
3414     }
3415   }
3416
3417   /* clear these for next connection */
3418   ftp->transfer = PPTRANSFER_BODY;
3419   ftpc->dont_check = FALSE;
3420
3421   /* Send any post-transfer QUOTE strings? */
3422   if(!status && !result && !premature && data->set.postquote)
3423     result = ftp_sendquote(data, conn, data->set.postquote);
3424   Curl_safefree(ftp->pathalloc);
3425   return result;
3426 }
3427
3428 /***********************************************************************
3429  *
3430  * ftp_sendquote()
3431  *
3432  * Where a 'quote' means a list of custom commands to send to the server.
3433  * The quote list is passed as an argument.
3434  *
3435  * BLOCKING
3436  */
3437
3438 static
3439 CURLcode ftp_sendquote(struct Curl_easy *data,
3440                        struct connectdata *conn, struct curl_slist *quote)
3441 {
3442   struct curl_slist *item;
3443   struct ftp_conn *ftpc = &conn->proto.ftpc;
3444   struct pingpong *pp = &ftpc->pp;
3445
3446   item = quote;
3447   while(item) {
3448     if(item->data) {
3449       ssize_t nread;
3450       char *cmd = item->data;
3451       bool acceptfail = FALSE;
3452       CURLcode result;
3453       int ftpcode = 0;
3454
3455       /* if a command starts with an asterisk, which a legal FTP command never
3456          can, the command will be allowed to fail without it causing any
3457          aborts or cancels etc. It will cause libcurl to act as if the command
3458          is successful, whatever the server reponds. */
3459
3460       if(cmd[0] == '*') {
3461         cmd++;
3462         acceptfail = TRUE;
3463       }
3464
3465       result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
3466       if(!result) {
3467         pp->response = Curl_now(); /* timeout relative now */
3468         result = Curl_GetFTPResponse(data, &nread, &ftpcode);
3469       }
3470       if(result)
3471         return result;
3472
3473       if(!acceptfail && (ftpcode >= 400)) {
3474         failf(data, "QUOT string not accepted: %s", cmd);
3475         return CURLE_QUOTE_ERROR;
3476       }
3477     }
3478
3479     item = item->next;
3480   }
3481
3482   return CURLE_OK;
3483 }
3484
3485 /***********************************************************************
3486  *
3487  * ftp_need_type()
3488  *
3489  * Returns TRUE if we in the current situation should send TYPE
3490  */
3491 static int ftp_need_type(struct connectdata *conn,
3492                          bool ascii_wanted)
3493 {
3494   return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I');
3495 }
3496
3497 /***********************************************************************
3498  *
3499  * ftp_nb_type()
3500  *
3501  * Set TYPE. We only deal with ASCII or BINARY so this function
3502  * sets one of them.
3503  * If the transfer type is not sent, simulate on OK response in newstate
3504  */
3505 static CURLcode ftp_nb_type(struct Curl_easy *data,
3506                             struct connectdata *conn,
3507                             bool ascii, ftpstate newstate)
3508 {
3509   struct ftp_conn *ftpc = &conn->proto.ftpc;
3510   CURLcode result;
3511   char want = (char)(ascii?'A':'I');
3512
3513   if(ftpc->transfertype == want) {
3514     state(data, newstate);
3515     return ftp_state_type_resp(data, 200, newstate);
3516   }
3517
3518   result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
3519   if(!result) {
3520     state(data, newstate);
3521
3522     /* keep track of our current transfer type */
3523     ftpc->transfertype = want;
3524   }
3525   return result;
3526 }
3527
3528 /***************************************************************************
3529  *
3530  * ftp_pasv_verbose()
3531  *
3532  * This function only outputs some informationals about this second connection
3533  * when we've issued a PASV command before and thus we have connected to a
3534  * possibly new IP address.
3535  *
3536  */
3537 #ifndef CURL_DISABLE_VERBOSE_STRINGS
3538 static void
3539 ftp_pasv_verbose(struct Curl_easy *data,
3540                  struct Curl_addrinfo *ai,
3541                  char *newhost, /* ascii version */
3542                  int port)
3543 {
3544   char buf[256];
3545   Curl_printable_address(ai, buf, sizeof(buf));
3546   infof(data, "Connecting to %s (%s) port %d", newhost, buf, port);
3547 }
3548 #endif
3549
3550 /*
3551  * ftp_do_more()
3552  *
3553  * This function shall be called when the second FTP (data) connection is
3554  * connected.
3555  *
3556  * 'complete' can return 0 for incomplete, 1 for done and -1 for go back
3557  * (which basically is only for when PASV is being sent to retry a failed
3558  * EPSV).
3559  */
3560
3561 static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
3562 {
3563   struct connectdata *conn = data->conn;
3564   struct ftp_conn *ftpc = &conn->proto.ftpc;
3565   CURLcode result = CURLE_OK;
3566   bool connected = FALSE;
3567   bool complete = FALSE;
3568
3569   /* the ftp struct is inited in ftp_connect(). If we are connecting to an HTTP
3570    * proxy then the state will not be valid until after that connection is
3571    * complete */
3572   struct FTP *ftp = NULL;
3573
3574   /* if the second connection isn't done yet, wait for it */
3575   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
3576     if(Curl_connect_ongoing(conn)) {
3577       /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
3578          aren't used so we blank their arguments. */
3579       result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0);
3580
3581       return result;
3582     }
3583
3584     result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected);
3585
3586     /* Ready to do more? */
3587     if(connected) {
3588       DEBUGF(infof(data, "DO-MORE connected phase starts"));
3589     }
3590     else {
3591       if(result && (ftpc->count1 == 0)) {
3592         *completep = -1; /* go back to DOING please */
3593         /* this is a EPSV connect failing, try PASV instead */
3594         return ftp_epsv_disable(data, conn);
3595       }
3596       return result;
3597     }
3598   }
3599
3600 #ifndef CURL_DISABLE_PROXY
3601   result = Curl_proxy_connect(data, SECONDARYSOCKET);
3602   if(result)
3603     return result;
3604
3605   if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
3606     return result;
3607
3608   if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
3609      Curl_connect_ongoing(conn))
3610     return result;
3611 #endif
3612
3613   /* Curl_proxy_connect might have moved the protocol state */
3614   ftp = data->req.p.ftp;
3615
3616   if(ftpc->state) {
3617     /* already in a state so skip the initial commands.
3618        They are only done to kickstart the do_more state */
3619     result = ftp_multi_statemach(data, &complete);
3620
3621     *completep = (int)complete;
3622
3623     /* if we got an error or if we don't wait for a data connection return
3624        immediately */
3625     if(result || !ftpc->wait_data_conn)
3626       return result;
3627
3628     /* if we reach the end of the FTP state machine here, *complete will be
3629        TRUE but so is ftpc->wait_data_conn, which says we need to wait for the
3630        data connection and therefore we're not actually complete */
3631     *completep = 0;
3632   }
3633
3634   if(ftp->transfer <= PPTRANSFER_INFO) {
3635     /* a transfer is about to take place, or if not a file name was given
3636        so we'll do a SIZE on it later and then we need the right TYPE first */
3637
3638     if(ftpc->wait_data_conn == TRUE) {
3639       bool serv_conned;
3640
3641       result = ReceivedServerConnect(data, &serv_conned);
3642       if(result)
3643         return result; /* Failed to accept data connection */
3644
3645       if(serv_conned) {
3646         /* It looks data connection is established */
3647         result = AcceptServerConnect(data);
3648         ftpc->wait_data_conn = FALSE;
3649         if(!result)
3650           result = InitiateTransfer(data);
3651
3652         if(result)
3653           return result;
3654
3655         *completep = 1; /* this state is now complete when the server has
3656                            connected back to us */
3657       }
3658     }
3659     else if(data->set.upload) {
3660       result = ftp_nb_type(data, conn, data->state.prefer_ascii,
3661                            FTP_STOR_TYPE);
3662       if(result)
3663         return result;
3664
3665       result = ftp_multi_statemach(data, &complete);
3666       if(ftpc->wait_data_conn)
3667         /* if we reach the end of the FTP state machine here, *complete will be
3668            TRUE but so is ftpc->wait_data_conn, which says we need to wait for
3669            the data connection and therefore we're not actually complete */
3670         *completep = 0;
3671       else
3672         *completep = (int)complete;
3673     }
3674     else {
3675       /* download */
3676       ftp->downloadsize = -1; /* unknown as of yet */
3677
3678       result = Curl_range(data);
3679
3680       if(result == CURLE_OK && data->req.maxdownload >= 0) {
3681         /* Don't check for successful transfer */
3682         ftpc->dont_check = TRUE;
3683       }
3684
3685       if(result)
3686         ;
3687       else if(data->state.list_only || !ftpc->file) {
3688         /* The specified path ends with a slash, and therefore we think this
3689            is a directory that is requested, use LIST. But before that we
3690            need to set ASCII transfer mode. */
3691
3692         /* But only if a body transfer was requested. */
3693         if(ftp->transfer == PPTRANSFER_BODY) {
3694           result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE);
3695           if(result)
3696             return result;
3697         }
3698         /* otherwise just fall through */
3699       }
3700       else {
3701         result = ftp_nb_type(data, conn, data->state.prefer_ascii,
3702                              FTP_RETR_TYPE);
3703         if(result)
3704           return result;
3705       }
3706
3707       result = ftp_multi_statemach(data, &complete);
3708       *completep = (int)complete;
3709     }
3710     return result;
3711   }
3712
3713   /* no data to transfer */
3714   Curl_setup_transfer(data, -1, -1, FALSE, -1);
3715
3716   if(!ftpc->wait_data_conn) {
3717     /* no waiting for the data connection so this is now complete */
3718     *completep = 1;
3719     DEBUGF(infof(data, "DO-MORE phase ends with %d", (int)result));
3720   }
3721
3722   return result;
3723 }
3724
3725
3726
3727 /***********************************************************************
3728  *
3729  * ftp_perform()
3730  *
3731  * This is the actual DO function for FTP. Get a file/directory according to
3732  * the options previously setup.
3733  */
3734
3735 static
3736 CURLcode ftp_perform(struct Curl_easy *data,
3737                      bool *connected,  /* connect status after PASV / PORT */
3738                      bool *dophase_done)
3739 {
3740   /* this is FTP and no proxy */
3741   CURLcode result = CURLE_OK;
3742   struct connectdata *conn = data->conn;
3743
3744   DEBUGF(infof(data, "DO phase starts"));
3745
3746   if(data->set.opt_no_body) {
3747     /* requested no body means no transfer... */
3748     struct FTP *ftp = data->req.p.ftp;
3749     ftp->transfer = PPTRANSFER_INFO;
3750   }
3751
3752   *dophase_done = FALSE; /* not done yet */
3753
3754   /* start the first command in the DO phase */
3755   result = ftp_state_quote(data, TRUE, FTP_QUOTE);
3756   if(result)
3757     return result;
3758
3759   /* run the state-machine */
3760   result = ftp_multi_statemach(data, dophase_done);
3761
3762   *connected = conn->bits.tcpconnect[SECONDARYSOCKET];
3763
3764   infof(data, "ftp_perform ends with SECONDARY: %d", *connected);
3765
3766   if(*dophase_done) {
3767     DEBUGF(infof(data, "DO phase is complete1"));
3768   }
3769
3770   return result;
3771 }
3772
3773 static void wc_data_dtor(void *ptr)
3774 {
3775   struct ftp_wc *ftpwc = ptr;
3776   if(ftpwc && ftpwc->parser)
3777     Curl_ftp_parselist_data_free(&ftpwc->parser);
3778   free(ftpwc);
3779 }
3780
3781 static CURLcode init_wc_data(struct Curl_easy *data)
3782 {
3783   char *last_slash;
3784   struct FTP *ftp = data->req.p.ftp;
3785   char *path = ftp->path;
3786   struct WildcardData *wildcard = &(data->wildcard);
3787   CURLcode result = CURLE_OK;
3788   struct ftp_wc *ftpwc = NULL;
3789
3790   last_slash = strrchr(ftp->path, '/');
3791   if(last_slash) {
3792     last_slash++;
3793     if(last_slash[0] == '\0') {
3794       wildcard->state = CURLWC_CLEAN;
3795       result = ftp_parse_url_path(data);
3796       return result;
3797     }
3798     wildcard->pattern = strdup(last_slash);
3799     if(!wildcard->pattern)
3800       return CURLE_OUT_OF_MEMORY;
3801     last_slash[0] = '\0'; /* cut file from path */
3802   }
3803   else { /* there is only 'wildcard pattern' or nothing */
3804     if(path[0]) {
3805       wildcard->pattern = strdup(path);
3806       if(!wildcard->pattern)
3807         return CURLE_OUT_OF_MEMORY;
3808       path[0] = '\0';
3809     }
3810     else { /* only list */
3811       wildcard->state = CURLWC_CLEAN;
3812       result = ftp_parse_url_path(data);
3813       return result;
3814     }
3815   }
3816
3817   /* program continues only if URL is not ending with slash, allocate needed
3818      resources for wildcard transfer */
3819
3820   /* allocate ftp protocol specific wildcard data */
3821   ftpwc = calloc(1, sizeof(struct ftp_wc));
3822   if(!ftpwc) {
3823     result = CURLE_OUT_OF_MEMORY;
3824     goto fail;
3825   }
3826
3827   /* INITIALIZE parselist structure */
3828   ftpwc->parser = Curl_ftp_parselist_data_alloc();
3829   if(!ftpwc->parser) {
3830     result = CURLE_OUT_OF_MEMORY;
3831     goto fail;
3832   }
3833
3834   wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
3835   wildcard->dtor = wc_data_dtor;
3836
3837   /* wildcard does not support NOCWD option (assert it?) */
3838   if(data->set.ftp_filemethod == FTPFILE_NOCWD)
3839     data->set.ftp_filemethod = FTPFILE_MULTICWD;
3840
3841   /* try to parse ftp url */
3842   result = ftp_parse_url_path(data);
3843   if(result) {
3844     goto fail;
3845   }
3846
3847   wildcard->path = strdup(ftp->path);
3848   if(!wildcard->path) {
3849     result = CURLE_OUT_OF_MEMORY;
3850     goto fail;
3851   }
3852
3853   /* backup old write_function */
3854   ftpwc->backup.write_function = data->set.fwrite_func;
3855   /* parsing write function */
3856   data->set.fwrite_func = Curl_ftp_parselist;
3857   /* backup old file descriptor */
3858   ftpwc->backup.file_descriptor = data->set.out;
3859   /* let the writefunc callback know the transfer */
3860   data->set.out = data;
3861
3862   infof(data, "Wildcard - Parsing started");
3863   return CURLE_OK;
3864
3865   fail:
3866   if(ftpwc) {
3867     Curl_ftp_parselist_data_free(&ftpwc->parser);
3868     free(ftpwc);
3869   }
3870   Curl_safefree(wildcard->pattern);
3871   wildcard->dtor = ZERO_NULL;
3872   wildcard->protdata = NULL;
3873   return result;
3874 }
3875
3876 static CURLcode wc_statemach(struct Curl_easy *data)
3877 {
3878   struct WildcardData * const wildcard = &(data->wildcard);
3879   struct connectdata *conn = data->conn;
3880   CURLcode result = CURLE_OK;
3881
3882   for(;;) {
3883     switch(wildcard->state) {
3884     case CURLWC_INIT:
3885       result = init_wc_data(data);
3886       if(wildcard->state == CURLWC_CLEAN)
3887         /* only listing! */
3888         return result;
3889       wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
3890       return result;
3891
3892     case CURLWC_MATCHING: {
3893       /* In this state is LIST response successfully parsed, so lets restore
3894          previous WRITEFUNCTION callback and WRITEDATA pointer */
3895       struct ftp_wc *ftpwc = wildcard->protdata;
3896       data->set.fwrite_func = ftpwc->backup.write_function;
3897       data->set.out = ftpwc->backup.file_descriptor;
3898       ftpwc->backup.write_function = ZERO_NULL;
3899       ftpwc->backup.file_descriptor = NULL;
3900       wildcard->state = CURLWC_DOWNLOADING;
3901
3902       if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
3903         /* error found in LIST parsing */
3904         wildcard->state = CURLWC_CLEAN;
3905         continue;
3906       }
3907       if(wildcard->filelist.size == 0) {
3908         /* no corresponding file */
3909         wildcard->state = CURLWC_CLEAN;
3910         return CURLE_REMOTE_FILE_NOT_FOUND;
3911       }
3912       continue;
3913     }
3914
3915     case CURLWC_DOWNLOADING: {
3916       /* filelist has at least one file, lets get first one */
3917       struct ftp_conn *ftpc = &conn->proto.ftpc;
3918       struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
3919       struct FTP *ftp = data->req.p.ftp;
3920
3921       char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
3922       if(!tmp_path)
3923         return CURLE_OUT_OF_MEMORY;
3924
3925       /* switch default ftp->path and tmp_path */
3926       free(ftp->pathalloc);
3927       ftp->pathalloc = ftp->path = tmp_path;
3928
3929       infof(data, "Wildcard - START of \"%s\"", finfo->filename);
3930       if(data->set.chunk_bgn) {
3931         long userresponse;
3932         Curl_set_in_callback(data, true);
3933         userresponse = data->set.chunk_bgn(
3934           finfo, wildcard->customptr, (int)wildcard->filelist.size);
3935         Curl_set_in_callback(data, false);
3936         switch(userresponse) {
3937         case CURL_CHUNK_BGN_FUNC_SKIP:
3938           infof(data, "Wildcard - \"%s\" skipped by user",
3939                 finfo->filename);
3940           wildcard->state = CURLWC_SKIP;
3941           continue;
3942         case CURL_CHUNK_BGN_FUNC_FAIL:
3943           return CURLE_CHUNK_FAILED;
3944         }
3945       }
3946
3947       if(finfo->filetype != CURLFILETYPE_FILE) {
3948         wildcard->state = CURLWC_SKIP;
3949         continue;
3950       }
3951
3952       if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
3953         ftpc->known_filesize = finfo->size;
3954
3955       result = ftp_parse_url_path(data);
3956       if(result)
3957         return result;
3958
3959       /* we don't need the Curl_fileinfo of first file anymore */
3960       Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
3961
3962       if(wildcard->filelist.size == 0) { /* remains only one file to down. */
3963         wildcard->state = CURLWC_CLEAN;
3964         /* after that will be ftp_do called once again and no transfer
3965            will be done because of CURLWC_CLEAN state */
3966         return CURLE_OK;
3967       }
3968       return result;
3969     }
3970
3971     case CURLWC_SKIP: {
3972       if(data->set.chunk_end) {
3973         Curl_set_in_callback(data, true);
3974         data->set.chunk_end(data->wildcard.customptr);
3975         Curl_set_in_callback(data, false);
3976       }
3977       Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
3978       wildcard->state = (wildcard->filelist.size == 0) ?
3979         CURLWC_CLEAN : CURLWC_DOWNLOADING;
3980       continue;
3981     }
3982
3983     case CURLWC_CLEAN: {
3984       struct ftp_wc *ftpwc = wildcard->protdata;
3985       result = CURLE_OK;
3986       if(ftpwc)
3987         result = Curl_ftp_parselist_geterror(ftpwc->parser);
3988
3989       wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
3990       return result;
3991     }
3992
3993     case CURLWC_DONE:
3994     case CURLWC_ERROR:
3995     case CURLWC_CLEAR:
3996       if(wildcard->dtor)
3997         wildcard->dtor(wildcard->protdata);
3998       return result;
3999     }
4000   }
4001   /* UNREACHABLE */
4002 }
4003
4004 /***********************************************************************
4005  *
4006  * ftp_do()
4007  *
4008  * This function is registered as 'curl_do' function. It decodes the path
4009  * parts etc as a wrapper to the actual DO function (ftp_perform).
4010  *
4011  * The input argument is already checked for validity.
4012  */
4013 static CURLcode ftp_do(struct Curl_easy *data, bool *done)
4014 {
4015   CURLcode result = CURLE_OK;
4016   struct connectdata *conn = data->conn;
4017   struct ftp_conn *ftpc = &conn->proto.ftpc;
4018
4019   *done = FALSE; /* default to false */
4020   ftpc->wait_data_conn = FALSE; /* default to no such wait */
4021
4022   if(data->state.wildcardmatch) {
4023     result = wc_statemach(data);
4024     if(data->wildcard.state == CURLWC_SKIP ||
4025       data->wildcard.state == CURLWC_DONE) {
4026       /* do not call ftp_regular_transfer */
4027       return CURLE_OK;
4028     }
4029     if(result) /* error, loop or skipping the file */
4030       return result;
4031   }
4032   else { /* no wildcard FSM needed */
4033     result = ftp_parse_url_path(data);
4034     if(result)
4035       return result;
4036   }
4037
4038   result = ftp_regular_transfer(data, done);
4039
4040   return result;
4041 }
4042
4043 /***********************************************************************
4044  *
4045  * ftp_quit()
4046  *
4047  * This should be called before calling sclose() on an ftp control connection
4048  * (not data connections). We should then wait for the response from the
4049  * server before returning. The calling code should then try to close the
4050  * connection.
4051  *
4052  */
4053 static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn)
4054 {
4055   CURLcode result = CURLE_OK;
4056
4057   if(conn->proto.ftpc.ctl_valid) {
4058     result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT");
4059     if(result) {
4060       failf(data, "Failure sending QUIT command: %s",
4061             curl_easy_strerror(result));
4062       conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
4063       connclose(conn, "QUIT command failed"); /* mark for connection closure */
4064       state(data, FTP_STOP);
4065       return result;
4066     }
4067
4068     state(data, FTP_QUIT);
4069
4070     result = ftp_block_statemach(data, conn);
4071   }
4072
4073   return result;
4074 }
4075
4076 /***********************************************************************
4077  *
4078  * ftp_disconnect()
4079  *
4080  * Disconnect from an FTP server. Cleanup protocol-specific per-connection
4081  * resources. BLOCKING.
4082  */
4083 static CURLcode ftp_disconnect(struct Curl_easy *data,
4084                                struct connectdata *conn,
4085                                bool dead_connection)
4086 {
4087   struct ftp_conn *ftpc = &conn->proto.ftpc;
4088   struct pingpong *pp = &ftpc->pp;
4089
4090   /* We cannot send quit unconditionally. If this connection is stale or
4091      bad in any way, sending quit and waiting around here will make the
4092      disconnect wait in vain and cause more problems than we need to.
4093
4094      ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
4095      will try to send the QUIT command, otherwise it will just return.
4096   */
4097   if(dead_connection)
4098     ftpc->ctl_valid = FALSE;
4099
4100   /* The FTP session may or may not have been allocated/setup at this point! */
4101   (void)ftp_quit(data, conn); /* ignore errors on the QUIT */
4102
4103   if(ftpc->entrypath) {
4104     if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
4105       data->state.most_recent_ftp_entrypath = NULL;
4106     }
4107     Curl_safefree(ftpc->entrypath);
4108   }
4109
4110   freedirs(ftpc);
4111   Curl_safefree(ftpc->prevpath);
4112   Curl_safefree(ftpc->server_os);
4113   Curl_pp_disconnect(pp);
4114   Curl_sec_end(conn);
4115   return CURLE_OK;
4116 }
4117
4118 #ifdef _MSC_VER
4119 /* warning C4706: assignment within conditional expression */
4120 #pragma warning(disable:4706)
4121 #endif
4122
4123 /***********************************************************************
4124  *
4125  * ftp_parse_url_path()
4126  *
4127  * Parse the URL path into separate path components.
4128  *
4129  */
4130 static
4131 CURLcode ftp_parse_url_path(struct Curl_easy *data)
4132 {
4133   /* the ftp struct is already inited in ftp_connect() */
4134   struct FTP *ftp = data->req.p.ftp;
4135   struct connectdata *conn = data->conn;
4136   struct ftp_conn *ftpc = &conn->proto.ftpc;
4137   const char *slashPos = NULL;
4138   const char *fileName = NULL;
4139   CURLcode result = CURLE_OK;
4140   char *rawPath = NULL; /* url-decoded "raw" path */
4141   size_t pathLen = 0;
4142
4143   ftpc->ctl_valid = FALSE;
4144   ftpc->cwdfail = FALSE;
4145
4146   /* url-decode ftp path before further evaluation */
4147   result = Curl_urldecode(ftp->path, 0, &rawPath, &pathLen, REJECT_CTRL);
4148   if(result) {
4149     failf(data, "path contains control characters");
4150     return result;
4151   }
4152
4153   switch(data->set.ftp_filemethod) {
4154     case FTPFILE_NOCWD: /* fastest, but less standard-compliant */
4155
4156       if((pathLen > 0) && (rawPath[pathLen - 1] != '/'))
4157           fileName = rawPath;  /* this is a full file path */
4158       /*
4159         else: ftpc->file is not used anywhere other than for operations on
4160               a file. In other words, never for directory operations.
4161               So we can safely leave filename as NULL here and use it as a
4162               argument in dir/file decisions.
4163       */
4164       break;
4165
4166     case FTPFILE_SINGLECWD:
4167       slashPos = strrchr(rawPath, '/');
4168       if(slashPos) {
4169         /* get path before last slash, except for / */
4170         size_t dirlen = slashPos - rawPath;
4171         if(dirlen == 0)
4172             dirlen++;
4173
4174         ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
4175         if(!ftpc->dirs) {
4176           free(rawPath);
4177           return CURLE_OUT_OF_MEMORY;
4178         }
4179
4180         ftpc->dirs[0] = calloc(1, dirlen + 1);
4181         if(!ftpc->dirs[0]) {
4182           free(rawPath);
4183           return CURLE_OUT_OF_MEMORY;
4184         }
4185
4186         strncpy(ftpc->dirs[0], rawPath, dirlen);
4187         ftpc->dirdepth = 1; /* we consider it to be a single dir */
4188         fileName = slashPos + 1; /* rest is file name */
4189       }
4190       else
4191         fileName = rawPath; /* file name only (or empty) */
4192       break;
4193
4194     default: /* allow pretty much anything */
4195     case FTPFILE_MULTICWD: {
4196       /* current position: begin of next path component */
4197       const char *curPos = rawPath;
4198
4199       int dirAlloc = 0; /* number of entries allocated for the 'dirs' array */
4200       const char *str = rawPath;
4201       for(; *str != 0; ++str)
4202         if (*str == '/')
4203           ++dirAlloc;
4204
4205       if(dirAlloc > 0) {
4206         ftpc->dirs = calloc(dirAlloc, sizeof(ftpc->dirs[0]));
4207         if(!ftpc->dirs) {
4208           free(rawPath);
4209           return CURLE_OUT_OF_MEMORY;
4210         }
4211
4212         /* parse the URL path into separate path components */
4213         while((slashPos = strchr(curPos, '/'))) {
4214           size_t compLen = slashPos - curPos;
4215
4216           /* path starts with a slash: add that as a directory */
4217           if((compLen == 0) && (ftpc->dirdepth == 0))
4218             ++compLen;
4219
4220           /* we skip empty path components, like "x//y" since the FTP command
4221              CWD requires a parameter and a non-existent parameter a) doesn't
4222              work on many servers and b) has no effect on the others. */
4223           if(compLen > 0) {
4224             char *comp = calloc(1, compLen + 1);
4225             if(!comp) {
4226               free(rawPath);
4227               return CURLE_OUT_OF_MEMORY;
4228             }
4229             strncpy(comp, curPos, compLen);
4230             ftpc->dirs[ftpc->dirdepth++] = comp;
4231           }
4232           curPos = slashPos + 1;
4233         }
4234       }
4235       DEBUGASSERT(ftpc->dirdepth <= dirAlloc);
4236       fileName = curPos; /* the rest is the file name (or empty) */
4237     }
4238     break;
4239   } /* switch */
4240
4241   if(fileName && *fileName)
4242     ftpc->file = strdup(fileName);
4243   else
4244     ftpc->file = NULL; /* instead of point to a zero byte,
4245                             we make it a NULL pointer */
4246
4247   if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
4248     /* We need a file name when uploading. Return error! */
4249     failf(data, "Uploading to a URL without a file name");
4250     free(rawPath);
4251     return CURLE_URL_MALFORMAT;
4252   }
4253
4254   ftpc->cwddone = FALSE; /* default to not done */
4255
4256   if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
4257     ftpc->cwddone = TRUE; /* skip CWD for absolute paths */
4258   else { /* newly created FTP connections are already in entry path */
4259     const char *oldPath = conn->bits.reuse ? ftpc->prevpath : "";
4260     if(oldPath) {
4261       size_t n = pathLen;
4262       if(data->set.ftp_filemethod == FTPFILE_NOCWD)
4263         n = 0; /* CWD to entry for relative paths */
4264       else
4265         n -= ftpc->file?strlen(ftpc->file):0;
4266
4267       if((strlen(oldPath) == n) && !strncmp(rawPath, oldPath, n)) {
4268         infof(data, "Request has same path as previous transfer");
4269         ftpc->cwddone = TRUE;
4270       }
4271     }
4272   }
4273
4274   free(rawPath);
4275   return CURLE_OK;
4276 }
4277
4278 /* call this when the DO phase has completed */
4279 static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
4280 {
4281   struct connectdata *conn = data->conn;
4282   struct FTP *ftp = data->req.p.ftp;
4283   struct ftp_conn *ftpc = &conn->proto.ftpc;
4284
4285   if(connected) {
4286     int completed;
4287     CURLcode result = ftp_do_more(data, &completed);
4288
4289     if(result) {
4290       close_secondarysocket(data, conn);
4291       return result;
4292     }
4293   }
4294
4295   if(ftp->transfer != PPTRANSFER_BODY)
4296     /* no data to transfer */
4297     Curl_setup_transfer(data, -1, -1, FALSE, -1);
4298   else if(!connected)
4299     /* since we didn't connect now, we want do_more to get called */
4300     conn->bits.do_more = TRUE;
4301
4302   ftpc->ctl_valid = TRUE; /* seems good */
4303
4304   return CURLE_OK;
4305 }
4306
4307 /* called from multi.c while DOing */
4308 static CURLcode ftp_doing(struct Curl_easy *data,
4309                           bool *dophase_done)
4310 {
4311   CURLcode result = ftp_multi_statemach(data, dophase_done);
4312
4313   if(result)
4314     DEBUGF(infof(data, "DO phase failed"));
4315   else if(*dophase_done) {
4316     result = ftp_dophase_done(data, FALSE /* not connected */);
4317
4318     DEBUGF(infof(data, "DO phase is complete2"));
4319   }
4320   return result;
4321 }
4322
4323 /***********************************************************************
4324  *
4325  * ftp_regular_transfer()
4326  *
4327  * The input argument is already checked for validity.
4328  *
4329  * Performs all commands done before a regular transfer between a local and a
4330  * remote host.
4331  *
4332  * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
4333  * ftp_done() function without finding any major problem.
4334  */
4335 static
4336 CURLcode ftp_regular_transfer(struct Curl_easy *data,
4337                               bool *dophase_done)
4338 {
4339   CURLcode result = CURLE_OK;
4340   bool connected = FALSE;
4341   struct connectdata *conn = data->conn;
4342   struct ftp_conn *ftpc = &conn->proto.ftpc;
4343   data->req.size = -1; /* make sure this is unknown at this point */
4344
4345   Curl_pgrsSetUploadCounter(data, 0);
4346   Curl_pgrsSetDownloadCounter(data, 0);
4347   Curl_pgrsSetUploadSize(data, -1);
4348   Curl_pgrsSetDownloadSize(data, -1);
4349
4350   ftpc->ctl_valid = TRUE; /* starts good */
4351
4352   result = ftp_perform(data,
4353                        &connected, /* have we connected after PASV/PORT */
4354                        dophase_done); /* all commands in the DO-phase done? */
4355
4356   if(!result) {
4357
4358     if(!*dophase_done)
4359       /* the DO phase has not completed yet */
4360       return CURLE_OK;
4361
4362     result = ftp_dophase_done(data, connected);
4363
4364     if(result)
4365       return result;
4366   }
4367   else
4368     freedirs(ftpc);
4369
4370   return result;
4371 }
4372
4373 static CURLcode ftp_setup_connection(struct Curl_easy *data,
4374                                      struct connectdata *conn)
4375 {
4376   char *type;
4377   struct FTP *ftp;
4378
4379   data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
4380   if(!ftp)
4381     return CURLE_OUT_OF_MEMORY;
4382
4383   ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
4384
4385   /* FTP URLs support an extension like ";type=<typecode>" that
4386    * we'll try to get now! */
4387   type = strstr(ftp->path, ";type=");
4388
4389   if(!type)
4390     type = strstr(conn->host.rawalloc, ";type=");
4391
4392   if(type) {
4393     char command;
4394     *type = 0;                     /* it was in the middle of the hostname */
4395     command = Curl_raw_toupper(type[6]);
4396
4397     switch(command) {
4398     case 'A': /* ASCII mode */
4399       data->state.prefer_ascii = TRUE;
4400       break;
4401
4402     case 'D': /* directory mode */
4403       data->state.list_only = TRUE;
4404       break;
4405
4406     case 'I': /* binary mode */
4407     default:
4408       /* switch off ASCII */
4409       data->state.prefer_ascii = FALSE;
4410       break;
4411     }
4412   }
4413
4414   /* get some initial data into the ftp struct */
4415   ftp->transfer = PPTRANSFER_BODY;
4416   ftp->downloadsize = 0;
4417   conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
4418
4419   return CURLE_OK;
4420 }
4421
4422 #endif /* CURL_DISABLE_FTP */