X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fftp-basic.c;h=7a512c6ed607478ea39373c88196ba773aa07a29;hp=4920f72523052679d049103bf4d04e8f2f55654f;hb=320cfdcb658e8d6556ae9dfd902c2db1db866a6b;hpb=b7c6c35be5930695cc64ef2d54d6f421f8511553 diff --git a/src/ftp-basic.c b/src/ftp-basic.c index 4920f725..7a512c6e 100644 --- a/src/ftp-basic.c +++ b/src/ftp-basic.c @@ -1,6 +1,7 @@ /* Basic FTP routines. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, + Inc. This file is part of GNU Wget. @@ -17,17 +18,18 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License 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 -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. */ +Additional permission under GNU GPL version 3 section 7 -#include +If you modify this program, or any covered work, by linking or +combining it with the OpenSSL project's OpenSSL library (or a +modified version of that library), containing parts covered by the +terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +grants you additional permission to convey the resulting work. +Corresponding Source for a non-source form of such a combination +shall include the source code for the parts of OpenSSL used as well +as that of the covered work. */ + +#include "wget.h" #include #include @@ -35,11 +37,7 @@ so, delete this exception statement from your version. */ #include #include -#ifdef HAVE_UNISTD_H -# include -#endif - -#include "wget.h" +#include #include "utils.h" #include "connect.h" #include "host.h" @@ -69,7 +67,7 @@ ftp_response (int fd, char **ret_line) return FTPRERR; /* Strip trailing CRLF before printing the line, so that - escnonprint doesn't include bogus \012 and \015. */ + quotting doesn't include bogus \012 and \015. */ p = strchr (line, '\0'); if (p > line && p[-1] == '\n') *--p = '\0'; @@ -77,9 +75,10 @@ ftp_response (int fd, char **ret_line) *--p = '\0'; if (opt.server_response) - logprintf (LOG_NOTQUIET, "%s\n", escnonprint (line)); + logprintf (LOG_NOTQUIET, "%s\n", + quotearg_style (escape_quoting_style, line)); else - DEBUGP (("%s\n", escnonprint (line))); + DEBUGP (("%s\n", quotearg_style (escape_quoting_style, line))); /* The last line of output is the one that begins with "ddd ". */ if (c_isdigit (line[0]) && c_isdigit (line[1]) && c_isdigit (line[2]) @@ -117,7 +116,8 @@ ftp_request (const char *command, const char *value) if (*p == '\r' || *p == '\n') *p = ' '; DEBUGP (("\nDetected newlines in %s \"%s\"; changing to %s \"%s\"\n", - command, escnonprint (value), command, escnonprint (defanged))); + command, quotearg_style (escape_quoting_style, value), + command, quotearg_style (escape_quoting_style, defanged))); /* Make VALUE point to the defanged copy of the string. */ value = defanged; } @@ -188,7 +188,7 @@ ftp_login (int csock, const char *acc, const char *pass) "331 s/key ", "331 opiekey " }; - int i; + size_t i; const char *seed = NULL; for (i = 0; i < countof (skey_head); i++) @@ -245,7 +245,7 @@ ftp_login (int csock, const char *acc, const char *pass) } static void -ip_address_to_port_repr (const ip_address *addr, int port, char *buf, +ip_address_to_port_repr (const ip_address *addr, int port, char *buf, size_t buflen) { unsigned char *ptr; @@ -321,7 +321,7 @@ ftp_port (int csock, int *local_sock) #ifdef ENABLE_IPV6 static void -ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf, +ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf, size_t buflen) { unsigned char *ptr = IP_INADDR_DATA (addr); @@ -330,18 +330,18 @@ ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf, assert (buflen >= 21 * 4); /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */ - switch (addr->family) + switch (addr->family) { - case AF_INET: - snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4, + 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: + 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[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; @@ -409,15 +409,15 @@ ftp_lprt (int csock, int *local_sock) } static void -ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf, +ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf, size_t buflen) { int afnum; - /* buf must contain the argument of EPRT (of the form |af|addr|port|). - * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr + /* 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); + assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5); /* Construct the argument of EPRT (of the form |af|addr|port|). */ afnum = (addr->family == AF_INET ? 1 : 2); @@ -436,8 +436,8 @@ ftp_eprt (int csock, int *local_sock) ip_address addr; int nwritten; int port; - /* Must contain the argument of EPRT (of the form |af|addr|port|). - * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr + /* 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) */ char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1]; @@ -524,7 +524,10 @@ ftp_pasv (int csock, ip_address *addr, int *port) for (s += 4; *s && !c_isdigit (*s); s++) ; if (!*s) - return FTPINVPASV; + { + xfree (respline); + return FTPINVPASV; + } for (i = 0; i < 6; i++) { tmp[i] = 0; @@ -586,14 +589,17 @@ ftp_lpsv (int csock, ip_address *addr, int *port) { xfree (respline); return FTPNOPASV; - } + } /* Parse the response. */ s = respline; for (s += 4; *s && !c_isdigit (*s); s++) ; if (!*s) - return FTPINVPASV; + { + xfree (respline); + return FTPINVPASV; + } /* First, get the address family */ af = 0; @@ -749,22 +755,19 @@ ftp_epsv (int csock, ip_address *ip, int *port) { xfree (respline); return FTPNOPASV; - } + } assert (respline != NULL); DEBUGP(("respline is %s\n", respline)); - /* Parse the response. */ - s = respline; - /* Skip the useless stuff and get what's inside the parentheses */ start = strchr (respline, '('); if (start == NULL) { xfree (respline); return FTPINVPASV; - } + } /* Skip the first two void fields */ s = start + 1; @@ -773,26 +776,26 @@ ftp_epsv (int csock, ip_address *ip, int *port) { xfree (respline); return FTPINVPASV; - } + } for (i = 0; i < 2; i++) { - if (*s++ != delim) + if (*s++ != delim) { xfree (respline); return FTPINVPASV; - } + } } /* Finally, get the port number */ - tport = 0; - for (i = 1; c_isdigit (*s); s++) + tport = 0; + for (i = 1; c_isdigit (*s); s++) { if (i > 5) { xfree (respline); return FTPINVPASV; - } + } tport = (*s - '0') + 10 * tport; } @@ -801,13 +804,13 @@ ftp_epsv (int csock, ip_address *ip, int *port) { xfree (respline); return FTPINVPASV; - } + } - if (*s++ != ')') + if (*s != ')') { xfree (respline); return FTPINVPASV; - } + } *port = tport; @@ -957,17 +960,33 @@ ftp_retr (int csock, const char *file) /* Sends the LIST command to the server. If FILE is NULL, send just `LIST' (no space). */ uerr_t -ftp_list (int csock, const char *file) +ftp_list (int csock, const char *file, bool avoid_list_a, bool avoid_list, + bool *list_a_used) { char *request, *respline; int nwritten; uerr_t err; bool ok = false; - int i = 0; - /* Try `LIST -a' first and revert to `LIST' in case of failure. */ - const char *list_commands[] = { "LIST -a", + size_t i = 0; + + *list_a_used = false; + + /* 2013-10-12 Andrea Urbani (matfanjol) + For more information about LIST and "LIST -a" please look at ftp.c, + function getftp, text "__LIST_A_EXPLANATION__". + + If somebody changes the following commands, please, checks also the + later "i" variable. */ + const char *list_commands[] = { "LIST -a", "LIST" }; + if (avoid_list_a) + { + i = countof (list_commands)- 1; + DEBUGP (("(skipping \"LIST -a\")")); + } + + do { /* Send request. */ request = ftp_request (list_commands[i], file); @@ -990,22 +1009,30 @@ ftp_list (int csock, const char *file) { err = FTPOK; ok = true; + /* Which list command was used? */ + *list_a_used = (i == 0); } - else + else { err = FTPRERR; } xfree (respline); } ++i; + if ((avoid_list) && (i == 1)) + { + /* I skip LIST */ + ++i; + DEBUGP (("(skipping \"LIST\")")); + } } while (i < countof (list_commands) && !ok); - + return err; } /* Sends the SYST command to the server. */ uerr_t -ftp_syst (int csock, enum stype *server_type) +ftp_syst (int csock, enum stype *server_type, enum ustype *unix_type) { char *request, *respline; int nwritten; @@ -1038,12 +1065,23 @@ ftp_syst (int csock, enum stype *server_type) first word of the server response)? */ request = strtok (NULL, " "); + *unix_type = UST_OTHER; + 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; + { + *server_type = ST_UNIX; + /* 2013-10-17 Andrea Urbani (matfanjol) + I check more in depth the system type */ + if (!strncasecmp (ftp_last_respline, "215 UNIX Type: L8", 17)) + *unix_type = UST_TYPE_L8; + else if (!strncasecmp (ftp_last_respline, + "215 UNIX MultiNet Unix Emulation V5.3(93)", 41)) + *unix_type = UST_MULTINET; + } else if (!strcasecmp (request, "WINDOWS_NT") || !strcasecmp (request, "WINDOWS2000")) *server_type = ST_WINNT; @@ -1134,9 +1172,9 @@ ftp_size (int csock, const char *file, wgint *size) } if (*respline == '5') { - /* + /* * Probably means SIZE isn't supported on this server. - * Error is nonfatal since SIZE isn't in RFC 959 + * Error is nonfatal since SIZE isn't in RFC 959 */ xfree (respline); *size = 0; @@ -1147,7 +1185,7 @@ ftp_size (int csock, const char *file, wgint *size) *size = str_to_wgint (respline + 4, NULL, 10); if (errno) { - /* + /* * Couldn't parse the response for some reason. On the (few) * tests I've done, the response is 213 with nothing else - * maybe something a bit more resilient is necessary. It's not a