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