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
-(at your option) any later version.
+ (at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
#endif
#include <sys/types.h>
-/* For inet_ntop. */
-#ifndef WINDOWS
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-
-#ifdef WINDOWS
-# include <winsock.h>
-#endif
-
#include "wget.h"
#include "utils.h"
-#include "rbuf.h"
#include "connect.h"
#include "host.h"
#include "ftp.h"
+#include "retr.h"
char ftp_last_respline[128];
line is 0-terminated. All the response lines but the last one are
skipped. The last line is determined as described in RFC959. */
uerr_t
-ftp_response (struct rbuf *rbuf, char **line)
+ftp_response (int fd, char **ret_line)
{
- int i;
- int bufsize = 40;
-
- *line = (char *)xmalloc (bufsize);
- do
+ while (1)
{
- for (i = 0; 1; i++)
- {
- int res;
- if (i > bufsize - 1)
- *line = (char *)xrealloc (*line, (bufsize <<= 1));
- res = RBUF_READCHAR (rbuf, *line + i);
- /* RES is number of bytes read. */
- if (res == 1)
- {
- if ((*line)[i] == '\n')
- {
- (*line)[i] = '\0';
- /* Get rid of \r. */
- if (i > 0 && (*line)[i - 1] == '\r')
- (*line)[i - 1] = '\0';
- break;
- }
- }
- else
- return FTPRERR;
- }
+ char *line = fd_read_line (fd);
+ if (!line)
+ return FTPRERR;
if (opt.server_response)
- logprintf (LOG_ALWAYS, "%s\n", *line);
+ logputs (LOG_NOTQUIET, line);
else
- DEBUGP (("%s\n", *line));
+ DEBUGP (("%s", line));
+ if (ISDIGIT (line[0]) && ISDIGIT (line[1]) && ISDIGIT (line[2])
+ && line[3] == ' ')
+ {
+ char *p = line + strlen (line);
+ if (p > line && p[-1] == '\n')
+ *--p = '\0';
+ if (p > line && p[-1] == '\r')
+ *--p = '\0';
+ strncpy (ftp_last_respline, line, sizeof (ftp_last_respline));
+ ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
+ *ret_line = line;
+ return FTPOK;
+ }
+ xfree (line);
}
- while (!(i >= 3 && ISDIGIT (**line) && ISDIGIT ((*line)[1]) &&
- ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
- strncpy (ftp_last_respline, *line, sizeof (ftp_last_respline));
- ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
- return FTPOK;
}
/* Returns the malloc-ed FTP request, ending with <CR><LF>, printing
/* Sends the USER and PASS commands to the server, to control
connection socket csock. */
uerr_t
-ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
+ftp_login (int csock, const char *acc, const char *pass)
{
uerr_t err;
char *request, *respline;
int nwritten;
/* Get greeting. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
xfree (respline);
/* Send USER username. */
request = ftp_request ("USER", acc);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
xfree (respline);
/* Send PASS password. */
request = ftp_request ("PASS", pass);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
server. Use acceptport after RETR, to get the socket of data
connection. */
uerr_t
-ftp_port (struct rbuf *rbuf, int *local_sock)
+ftp_port (int csock, int *local_sock)
{
uerr_t err;
char *request, *respline;
/* Must contain the argument of PORT (of the form a,b,c,d,e,f). */
char bytes[6 * 4 + 1];
- assert (rbuf != NULL);
- assert (rbuf_initialized_p (rbuf));
-
/* Get the address of this side of the connection. */
- if (!conaddr (RBUF_FD (rbuf), &addr))
- return BINDERR;
+ if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
+ return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS);
port = 0;
/* Bind the port. */
- err = bindport (&addr, &port, local_sock);
- if (err != BINDOK)
- return err;
+ *local_sock = bind_local (&addr, &port);
+ if (*local_sock < 0)
+ return FTPSYSERR;
/* Construct the argument of PORT (of the form a,b,c,d,e,f). */
ip_address_to_port_repr (&addr, port, bytes, sizeof (bytes));
/* Send PORT request. */
request = ftp_request ("PORT", bytes);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
- xclose (*local_sock);
+ fd_close (*local_sock);
return WRITEFAILED;
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
- xclose (*local_sock);
+ fd_close (*local_sock);
return err;
}
if (*respline != '2')
{
xfree (respline);
- xclose (*local_sock);
+ fd_close (*local_sock);
return FTPPORTERR;
}
xfree (respline);
server. Use acceptport after RETR, to get the socket of data
connection. */
uerr_t
-ftp_lprt (struct rbuf *rbuf, int *local_sock)
+ftp_lprt (int csock, int *local_sock)
{
uerr_t err;
char *request, *respline;
/* Must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
char bytes[21 * 4 + 1];
- assert (rbuf != NULL);
- assert (rbuf_initialized_p (rbuf));
-
/* Get the address of this side of the connection. */
- if (!conaddr (RBUF_FD (rbuf), &addr))
- return BINDERR;
+ if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
+ return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
port = 0;
/* Bind the port. */
- err = bindport (&addr, &port, local_sock);
- if (err != BINDOK)
- return err;
+ *local_sock = bind_local (&addr, &port);
+ if (*local_sock < 0)
+ return FTPSYSERR;
/* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
ip_address_to_lprt_repr (&addr, port, bytes, sizeof (bytes));
/* Send PORT request. */
request = ftp_request ("LPRT", bytes);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
- xclose (*local_sock);
+ fd_close (*local_sock);
return WRITEFAILED;
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
- xclose (*local_sock);
+ fd_close (*local_sock);
return err;
}
if (*respline != '2')
{
xfree (respline);
- xclose (*local_sock);
+ fd_close (*local_sock);
return FTPPORTERR;
}
xfree (respline);
server. Use acceptport after RETR, to get the socket of data
connection. */
uerr_t
-ftp_eprt (struct rbuf *rbuf, int *local_sock)
+ftp_eprt (int csock, int *local_sock)
{
uerr_t err;
char *request, *respline;
* 1 char for af (1-2) and 5 chars for port (0-65535) */
char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1];
- assert (rbuf != NULL);
- assert (rbuf_initialized_p(rbuf));
-
/* Get the address of this side of the connection. */
- if (!conaddr (RBUF_FD (rbuf), &addr))
- return BINDERR;
+ if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
+ return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
port = 0;
/* Bind the port. */
- err = bindport (&addr, &port, local_sock);
- if (err != BINDOK)
- return err;
+ *local_sock = bind_local (&addr, &port);
+ if (*local_sock < 0)
+ return FTPSYSERR;
/* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
ip_address_to_eprt_repr (&addr, port, bytes, sizeof (bytes));
/* Send PORT request. */
request = ftp_request ("EPRT", bytes);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
- xclose (*local_sock);
+ fd_close (*local_sock);
return WRITEFAILED;
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
- xclose (*local_sock);
+ fd_close (*local_sock);
return err;
}
if (*respline != '2')
{
xfree (respline);
- xclose (*local_sock);
+ fd_close (*local_sock);
return FTPPORTERR;
}
xfree (respline);
transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */
uerr_t
-ftp_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
+ftp_pasv (int csock, ip_address *addr, int *port)
{
char *request, *respline, *s;
int nwritten, i;
uerr_t err;
unsigned char tmp[6];
- assert (rbuf != NULL);
- assert (rbuf_initialized_p (rbuf));
assert (addr != NULL);
assert (port != NULL);
/* Form the request. */
request = ftp_request ("PASV", NULL);
/* And send it. */
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get the server response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */
uerr_t
-ftp_lpsv (struct rbuf *rbuf, ip_address *addr, int *port)
+ftp_lpsv (int csock, ip_address *addr, int *port)
{
char *request, *respline, *s;
int nwritten, i, af, addrlen, portlen;
unsigned char tmp[16];
unsigned char tmpprt[2];
- assert (rbuf != NULL);
- assert (rbuf_initialized_p(rbuf));
assert (addr != NULL);
assert (port != NULL);
request = ftp_request ("LPSV", NULL);
/* And send it. */
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
xfree (request);
/* Get the server response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */
uerr_t
-ftp_epsv (struct rbuf *rbuf, ip_address *ip, int *port)
+ftp_epsv (int csock, ip_address *ip, int *port)
{
char *request, *respline, *start, delim, *s;
int nwritten, i;
uerr_t err;
int tport;
- socklen_t addrlen;
- struct sockaddr_storage ss;
- struct sockaddr *sa = (struct sockaddr *)&ss;
- assert (rbuf != NULL);
- assert (rbuf_initialized_p(rbuf));
assert (ip != NULL);
assert (port != NULL);
- addrlen = sizeof (ss);
- if (getpeername (rbuf->fd, sa, &addrlen) < 0)
- /* Mauro Tortonesi: HOW DO WE HANDLE THIS ERROR? */
- return CONPORTERR;
-
- assert (sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
-
- sockaddr_get_data (sa, ip, NULL);
+ /* IP already contains the IP address of the control connection's
+ peer, so we don't need to call socket_ip_address here. */
/* Form the request. */
/* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */
- request = ftp_request ("EPSV", (sa->sa_family == AF_INET ? "1" : "2"));
+ request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2"));
/* And send it. */
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
xfree (request);
/* Get the server response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
/* Sends the TYPE request to the server. */
uerr_t
-ftp_type (struct rbuf *rbuf, int type)
+ftp_type (int csock, int type)
{
char *request, *respline;
int nwritten;
stype[1] = 0;
/* Send TYPE request. */
request = ftp_request ("TYPE", stype);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
/* Changes the working directory by issuing a CWD command to the
server. */
uerr_t
-ftp_cwd (struct rbuf *rbuf, const char *dir)
+ftp_cwd (int csock, const char *dir)
{
char *request, *respline;
int nwritten;
/* Send CWD request. */
request = ftp_request ("CWD", dir);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
/* Sends REST command to the FTP server. */
uerr_t
-ftp_rest (struct rbuf *rbuf, long offset)
+ftp_rest (int csock, long offset)
{
char *request, *respline;
int nwritten;
number_to_string (numbuf, offset);
request = ftp_request ("REST", numbuf);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
/* Sends RETR command to the FTP server. */
uerr_t
-ftp_retr (struct rbuf *rbuf, const char *file)
+ftp_retr (int csock, const char *file)
{
char *request, *respline;
int nwritten;
/* Send RETR request. */
request = ftp_request ("RETR", file);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
/* Sends the LIST command to the server. If FILE is NULL, send just
`LIST' (no space). */
uerr_t
-ftp_list (struct rbuf *rbuf, const char *file)
+ftp_list (int csock, const char *file)
{
char *request, *respline;
int nwritten;
/* Send LIST request. */
request = ftp_request ("LIST", file);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate respone. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
/* Sends the SYST command to the server. */
uerr_t
-ftp_syst (struct rbuf *rbuf, enum stype *server_type)
+ftp_syst (int csock, enum stype *server_type)
{
char *request, *respline;
int nwritten;
/* Send SYST request. */
request = ftp_request ("SYST", NULL);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
*server_type = ST_VMS;
else if (!strcasecmp (request, "UNIX"))
*server_type = ST_UNIX;
- else if (!strcasecmp (request, "WINDOWS_NT"))
+ else if (!strcasecmp (request, "WINDOWS_NT")
+ || !strcasecmp (request, "WINDOWS2000"))
*server_type = ST_WINNT;
else if (!strcasecmp (request, "MACOS"))
*server_type = ST_MACOS;
/* Sends the PWD command to the server. */
uerr_t
-ftp_pwd (struct rbuf *rbuf, char **pwd)
+ftp_pwd (int csock, char **pwd)
{
char *request, *respline;
int nwritten;
/* Send PWD request. */
request = ftp_request ("PWD", NULL);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);
/* Sends the SIZE command to the server, and returns the value in 'size'.
* If an error occurs, size is set to zero. */
uerr_t
-ftp_size (struct rbuf *rbuf, const char *file, long int *size)
+ftp_size (int csock, const char *file, long int *size)
{
char *request, *respline;
int nwritten;
/* Send PWD request. */
request = ftp_request ("SIZE", file);
- nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
+ nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0)
{
xfree (request);
}
xfree (request);
/* Get appropriate response. */
- err = ftp_response (rbuf, &respline);
+ err = ftp_response (csock, &respline);
if (err != FTPOK)
{
xfree (respline);