X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fftp-basic.c;h=24026e194d89f0bff978e504ded1ab58189dea07;hp=5c38be024fbb40838957cd009fecbdbe9567d235;hb=4d7c5e087b2bc82c9f503dff003916d1047903ce;hpb=430f5f3b1eb05387eb6b7e8ba03772c434819165 diff --git a/src/ftp-basic.c b/src/ftp-basic.c index 5c38be02..24026e19 100644 --- a/src/ftp-basic.c +++ b/src/ftp-basic.c @@ -1,11 +1,11 @@ /* Basic FTP routines. - Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + Copyright (C) 1996-2007 Free Software Foundation, Inc. This file is part of GNU Wget. GNU Wget is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Wget is distributed in the hope that it will be useful, @@ -14,8 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Wget; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +along with Wget. If not, see . In addition, as a special exception, the Free Software Foundation gives permission to link the code of its release of Wget with the @@ -34,15 +33,10 @@ so, delete this exception statement from your version. */ #include #include -#ifdef HAVE_STRING_H -# include -#else -# include -#endif +#include #ifdef HAVE_UNISTD_H # include #endif -#include #include "wget.h" #include "utils.h" @@ -164,7 +158,7 @@ ftp_login (int csock, const char *acc, const char *pass) xfree (respline); /* Send USER username. */ request = ftp_request ("USER", acc); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -228,7 +222,7 @@ ftp_login (int csock, const char *acc, const char *pass) xfree (respline); /* Send PASS password. */ request = ftp_request ("PASS", pass); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -255,13 +249,11 @@ ip_address_to_port_repr (const ip_address *addr, int port, char *buf, { unsigned char *ptr; - assert (addr != NULL); - assert (addr->type == IPV4_ADDRESS); - assert (buf != NULL); + assert (addr->family == AF_INET); /* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */ assert (buflen >= 6 * 4); - ptr = ADDRESS_IPV4_DATA (addr); + ptr = IP_INADDR_DATA (addr); snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1], ptr[2], ptr[3], (port & 0xff00) >> 8, port & 0xff); buf[buflen - 1] = '\0'; @@ -285,7 +277,7 @@ ftp_port (int csock, int *local_sock) if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL)) return FTPSYSERR; - assert (addr.type == IPV4_ADDRESS); + assert (addr.family == AF_INET); /* Setting port to 0 lets the system choose a free port. */ port = 0; @@ -300,7 +292,7 @@ ftp_port (int csock, int *local_sock) /* Send PORT request. */ request = ftp_request ("PORT", bytes); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -331,32 +323,29 @@ static void ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf, size_t buflen) { - unsigned char *ptr; + unsigned char *ptr = IP_INADDR_DATA (addr); - assert (addr != NULL); - assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS); - assert (buf != NULL); /* buf must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */ assert (buflen >= 21 * 4); /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */ - switch (addr->type) - { - case IPV4_ADDRESS: - ptr = ADDRESS_IPV4_DATA (addr); - snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4, - ptr[0], ptr[1], ptr[2], ptr[3], 2, - (port & 0xff00) >> 8, port & 0xff); - buf[buflen - 1] = '\0'; - break; - case IPV6_ADDRESS: - ptr = ADDRESS_IPV6_DATA (addr); - snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", - 6, 16, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], - ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], 2, - (port & 0xff00) >> 8, port & 0xff); - buf[buflen - 1] = '\0'; - break; + switch (addr->family) + { + case AF_INET: + snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4, + ptr[0], ptr[1], ptr[2], ptr[3], 2, + (port & 0xff00) >> 8, port & 0xff); + break; + case AF_INET6: + snprintf (buf, buflen, + "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", + 6, 16, + ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], + ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], + 2, (port & 0xff00) >> 8, port & 0xff); + break; + default: + abort (); } } @@ -378,7 +367,7 @@ ftp_lprt (int csock, int *local_sock) if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL)) return FTPSYSERR; - assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS); + assert (addr.family == AF_INET || addr.family == AF_INET6); /* Setting port to 0 lets the system choose a free port. */ port = 0; @@ -393,7 +382,7 @@ ftp_lprt (int csock, int *local_sock) /* Send PORT request. */ request = ftp_request ("LPRT", bytes); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -424,17 +413,14 @@ ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf, { int afnum; - assert (addr != NULL); - assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS); - assert (buf != NULL); /* buf must contain the argument of EPRT (of the form |af|addr|port|). * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr * 1 char for af (1-2) and 5 chars for port (0-65535) */ assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5); /* Construct the argument of EPRT (of the form |af|addr|port|). */ - afnum = (addr->type == IPV4_ADDRESS ? 1 : 2); - snprintf (buf, buflen, "|%d|%s|%d|", afnum, pretty_print_address (addr), port); + afnum = (addr->family == AF_INET ? 1 : 2); + snprintf (buf, buflen, "|%d|%s|%d|", afnum, print_address (addr), port); buf[buflen - 1] = '\0'; } @@ -450,7 +436,7 @@ ftp_eprt (int csock, int *local_sock) int nwritten; int port; /* Must contain the argument of EPRT (of the form |af|addr|port|). - * 4 chars for the | separators, ENABLE_IPV6_ADDRSTRLEN chars for addr + * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr * 1 char for af (1-2) and 5 chars for port (0-65535) */ char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1]; @@ -458,8 +444,6 @@ ftp_eprt (int csock, int *local_sock) if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL)) return FTPSYSERR; - assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS); - /* Setting port to 0 lets the system choose a free port. */ port = 0; @@ -468,12 +452,12 @@ ftp_eprt (int csock, int *local_sock) if (*local_sock < 0) return FTPSYSERR; - /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */ + /* Construct the argument of EPRT (of the form |af|addr|port|). */ ip_address_to_eprt_repr (&addr, port, bytes, sizeof (bytes)); /* Send PORT request. */ request = ftp_request ("EPRT", bytes); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -518,7 +502,7 @@ ftp_pasv (int csock, ip_address *addr, int *port) /* Form the request. */ request = ftp_request ("PASV", NULL); /* And send it. */ - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -536,7 +520,8 @@ ftp_pasv (int csock, ip_address *addr, int *port) } /* Parse the request. */ s = respline; - for (s += 4; *s && !ISDIGIT (*s); s++); + for (s += 4; *s && !ISDIGIT (*s); s++) + ; if (!*s) return FTPINVPASV; for (i = 0; i < 6; i++) @@ -555,8 +540,8 @@ ftp_pasv (int csock, ip_address *addr, int *port) } xfree (respline); - addr->type = IPV4_ADDRESS; - memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4); + addr->family = AF_INET; + memcpy (IP_INADDR_DATA (addr), tmp, 4); *port = ((tmp[4] << 8) & 0xff00) + tmp[5]; return FTPOK; @@ -584,7 +569,7 @@ ftp_lpsv (int csock, ip_address *addr, int *port) request = ftp_request ("LPSV", NULL); /* And send it. */ - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -604,7 +589,8 @@ ftp_lpsv (int csock, ip_address *addr, int *port) /* Parse the response. */ s = respline; - for (s += 4; *s && !ISDIGIT (*s); s++); + for (s += 4; *s && !ISDIGIT (*s); s++) + ; if (!*s) return FTPINVPASV; @@ -700,10 +686,10 @@ ftp_lpsv (int csock, ip_address *addr, int *port) if (af == 4) { - addr->type = IPV4_ADDRESS; - memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4); + addr->family = AF_INET; + memcpy (IP_INADDR_DATA (addr), tmp, 4); *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1]; - DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr))); + DEBUGP (("lpsv addr is: %s\n", print_address(addr))); DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0])); DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1])); DEBUGP (("*port is: %d\n", *port)); @@ -711,10 +697,10 @@ ftp_lpsv (int csock, ip_address *addr, int *port) else { assert (af == 6); - addr->type = IPV6_ADDRESS; - memcpy (ADDRESS_IPV6_DATA (addr), tmp, 16); + addr->family = AF_INET6; + memcpy (IP_INADDR_DATA (addr), tmp, 16); *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1]; - DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr))); + DEBUGP (("lpsv addr is: %s\n", print_address(addr))); DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0])); DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1])); DEBUGP (("*port is: %d\n", *port)); @@ -743,10 +729,10 @@ ftp_epsv (int csock, ip_address *ip, int *port) /* Form the request. */ /* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */ - request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2")); + request = ftp_request ("EPSV", (ip->family == AF_INET ? "1" : "2")); /* And send it. */ - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -843,7 +829,7 @@ ftp_type (int csock, int type) stype[1] = 0; /* Send TYPE request. */ request = ftp_request ("TYPE", stype); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -875,7 +861,7 @@ ftp_cwd (int csock, const char *dir) /* Send CWD request. */ request = ftp_request ("CWD", dir); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -910,7 +896,7 @@ ftp_rest (int csock, wgint offset) uerr_t err; request = ftp_request ("REST", number_to_static_string (offset)); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -941,7 +927,7 @@ ftp_retr (int csock, const char *file) /* Send RETR request. */ request = ftp_request ("RETR", file); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -975,33 +961,45 @@ ftp_list (int csock, const char *file) char *request, *respline; int nwritten; uerr_t err; - - /* Send LIST request. */ - request = ftp_request ("LIST", file); - nwritten = fd_write (csock, request, strlen (request), -1.0); - if (nwritten < 0) - { - xfree (request); - return WRITEFAILED; - } - xfree (request); - /* Get appropriate respone. */ - err = ftp_response (csock, &respline); - if (err != FTPOK) - return err; - if (*respline == '5') - { - xfree (respline); - return FTPNSFOD; - } - if (*respline != '1') - { - xfree (respline); - return FTPRERR; - } - xfree (respline); - /* All OK. */ - return FTPOK; + bool ok = false; + int i = 0; + /* Try `LIST -a' first and revert to `LIST' in case of failure. */ + const char *list_commands[] = { "LIST -a", + "LIST" }; + + do { + /* Send request. */ + request = ftp_request (list_commands[i], file); + nwritten = fd_write (csock, request, strlen (request), -1); + if (nwritten < 0) + { + xfree (request); + return WRITEFAILED; + } + xfree (request); + /* Get appropriate response. */ + err = ftp_response (csock, &respline); + if (err == FTPOK) + { + if (*respline == '5') + { + err = FTPNSFOD; + } + else if (*respline == '1') + { + err = FTPOK; + ok = true; + } + else + { + err = FTPRERR; + } + xfree (respline); + } + ++i; + } while (i < countof (list_commands) && !ok); + + return err; } /* Sends the SYST command to the server. */ @@ -1014,7 +1012,7 @@ ftp_syst (int csock, enum stype *server_type) /* Send SYST request. */ request = ftp_request ("SYST", NULL); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -1039,7 +1037,9 @@ ftp_syst (int csock, enum stype *server_type) first word of the server response)? */ request = strtok (NULL, " "); - if (!strcasecmp (request, "VMS")) + if (request == NULL) + *server_type = ST_OTHER; + else if (!strcasecmp (request, "VMS")) *server_type = ST_VMS; else if (!strcasecmp (request, "UNIX")) *server_type = ST_UNIX; @@ -1068,7 +1068,7 @@ ftp_pwd (int csock, char **pwd) /* Send PWD request. */ request = ftp_request ("PWD", NULL); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request); @@ -1081,6 +1081,7 @@ ftp_pwd (int csock, char **pwd) return err; if (*respline == '5') { + err: xfree (respline); return FTPSRVERR; } @@ -1089,6 +1090,10 @@ ftp_pwd (int csock, char **pwd) and everything following it. */ strtok (respline, "\""); request = strtok (NULL, "\""); + if (!request) + /* Treat the malformed response as an error, which the caller has + to handle gracefully anyway. */ + goto err; /* Has the `pwd' been already allocated? Free! */ xfree_null (*pwd); @@ -1111,7 +1116,7 @@ ftp_size (int csock, const char *file, wgint *size) /* Send PWD request. */ request = ftp_request ("SIZE", file); - nwritten = fd_write (csock, request, strlen (request), -1.0); + nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { xfree (request);