[Midnightbsd-cvs] src: lib/libfetch: Merge in changes from FreeBSD CURRENT and Dragonfly
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Wed Jul 9 14:57:21 EDT 2008
Log Message:
-----------
Merge in changes from FreeBSD CURRENT and Dragonfly
Modified Files:
--------------
src/lib/libfetch:
Makefile (r1.1.1.1 -> r1.2)
common.c (r1.1.1.1 -> r1.2)
common.h (r1.1.1.1 -> r1.2)
fetch.3 (r1.1.1.1 -> r1.2)
fetch.c (r1.1.1.1 -> r1.2)
fetch.h (r1.1.1.1 -> r1.2)
file.c (r1.1.1.1 -> r1.2)
ftp.c (r1.1.1.1 -> r1.2)
ftp.errors (r1.1.1.1 -> r1.2)
http.c (r1.1.1.1 -> r1.2)
http.errors (r1.1.1.1 -> r1.2)
-------------- next part --------------
Index: file.c
===================================================================
RCS file: /home/cvs/src/lib/libfetch/file.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/file.c -L lib/libfetch/file.c -u -r1.1.1.1 -r1.2
--- lib/libfetch/file.c
+++ lib/libfetch/file.c
@@ -24,10 +24,12 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libfetch/file.c,v 1.18 2007/12/14 10:26:58 des Exp $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libfetch/file.c,v 1.17 2004/09/21 18:35:20 des Exp $");
+__MBSDID("$MidnightBSD$");
#include <sys/param.h>
#include <sys/stat.h>
@@ -50,11 +52,11 @@
f = fopen(u->doc, "r");
if (f == NULL)
- _fetch_syserr();
+ fetch_syserr();
if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) {
fclose(f);
- _fetch_syserr();
+ fetch_syserr();
}
return (f);
@@ -77,25 +79,25 @@
f = fopen(u->doc, "w+");
if (f == NULL)
- _fetch_syserr();
+ fetch_syserr();
if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) {
fclose(f);
- _fetch_syserr();
+ fetch_syserr();
}
return (f);
}
static int
-_fetch_stat_file(const char *fn, struct url_stat *us)
+fetch_stat_file(const char *fn, struct url_stat *us)
{
struct stat sb;
us->size = -1;
us->atime = us->mtime = 0;
if (stat(fn, &sb) == -1) {
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
us->size = sb.st_size;
@@ -107,7 +109,7 @@
int
fetchStatFile(struct url *u, struct url_stat *us, const char *flags __unused)
{
- return (_fetch_stat_file(u->doc, us));
+ return (fetch_stat_file(u->doc, us));
}
struct url_ent *
@@ -122,7 +124,7 @@
int l;
if ((dir = opendir(u->doc)) == NULL) {
- _fetch_syserr();
+ fetch_syserr();
return (NULL);
}
@@ -136,10 +138,10 @@
while ((de = readdir(dir)) != NULL) {
strncpy(p, de->d_name, l - 1);
p[l - 1] = 0;
- if (_fetch_stat_file(fn, &us) == -1)
+ if (fetch_stat_file(fn, &us) == -1)
/* should I return a partial result, or abort? */
break;
- _fetch_add_entry(&ue, &size, &len, de->d_name, &us);
+ fetch_add_entry(&ue, &size, &len, de->d_name, &us);
}
return (ue);
Index: fetch.3
===================================================================
RCS file: /home/cvs/src/lib/libfetch/fetch.3,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/fetch.3 -L lib/libfetch/fetch.3 -u -r1.1.1.1 -r1.2
--- lib/libfetch/fetch.3
+++ lib/libfetch/fetch.3
@@ -23,9 +23,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libfetch/fetch.3,v 1.60.2.1 2005/11/30 04:19:40 tmclaugh Exp $
+.\" $MidnightBSD$
+.\" $FreeBSD: src/lib/libfetch/fetch.3,v 1.65 2008/02/08 09:44:34 des Exp $
.\"
-.Dd July 1, 1998
+.Dd July 9, 2008
.Dt FETCH 3
.Os
.Sh NAME
@@ -236,7 +237,7 @@
.In fetch.h :
.Bd -literal
struct url_ent {
- char name[MAXPATHLEN];
+ char name[PATH_MAX];
struct url_stat stat;
};
.Ed
@@ -532,6 +533,14 @@
.Xr ftp 1
for a description of the file format.
This feature is experimental.
+.It Ev NO_PROXY
+Either a single asterisk, which disables the use of proxies
+altogether, or a comma- or whitespace-separated list of hosts for
+which proxies should not be used.
+.It Ev no_proxy
+Same as
+.Ev NO_PROXY ,
+for compatibility.
.El
.Sh EXAMPLES
To access a proxy server on
@@ -555,6 +564,14 @@
HTTP_PROXY=http://proxy.example.com:8080
HTTP_PROXY_AUTH=basic:*:<user>:<pwd>
.Ed
+.Pp
+To disable the use of a proxy for an HTTP server running on the local
+host, define
+.Ev NO_PROXY
+as follows:
+.Bd -literal -offset indent
+NO_PROXY=localhost,127.0.0.1
+.Ed
.Sh SEE ALSO
.Xr fetch 1 ,
.Xr ftpio 3 ,
Index: common.c
===================================================================
RCS file: /home/cvs/src/lib/libfetch/common.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/common.c -L lib/libfetch/common.c -u -r1.1.1.1 -r1.2
--- lib/libfetch/common.c
+++ lib/libfetch/common.c
@@ -24,17 +24,21 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libfetch/common.c,v 1.56 2008/04/15 23:29:51 cperciva Exp $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libfetch/common.c,v 1.50 2005/02/16 12:46:46 des Exp $");
+__MBSDID("$MidnightBSD$");
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
+
#include <netinet/in.h>
+#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <pwd.h>
@@ -53,7 +57,7 @@
/*
* Error messages for resolver errors
*/
-static struct fetcherr _netdb_errlist[] = {
+static struct fetcherr netdb_errlist[] = {
#ifdef EAI_NODATA
{ EAI_NODATA, FETCH_RESOLV, "Host not found" },
#endif
@@ -73,7 +77,7 @@
* Map error code to string
*/
static struct fetcherr *
-_fetch_finderr(struct fetcherr *p, int e)
+fetch_finderr(struct fetcherr *p, int e)
{
while (p->num != -1 && p->num != e)
p++;
@@ -84,9 +88,9 @@
* Set error code
*/
void
-_fetch_seterr(struct fetcherr *p, int e)
+fetch_seterr(struct fetcherr *p, int e)
{
- p = _fetch_finderr(p, e);
+ p = fetch_finderr(p, e);
fetchLastErrCode = p->cat;
snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string);
}
@@ -95,7 +99,7 @@
* Set error code according to errno
*/
void
-_fetch_syserr(void)
+fetch_syserr(void)
{
switch (errno) {
case 0:
@@ -155,7 +159,7 @@
* Emit status message
*/
void
-_fetch_info(const char *fmt, ...)
+fetch_info(const char *fmt, ...)
{
va_list ap;
@@ -172,7 +176,7 @@
* Return the default port for a scheme
*/
int
-_fetch_default_port(const char *scheme)
+fetch_default_port(const char *scheme)
{
struct servent *se;
@@ -189,7 +193,7 @@
* Return the default proxy port for a scheme
*/
int
-_fetch_default_proxy_port(const char *scheme)
+fetch_default_proxy_port(const char *scheme)
{
if (strcasecmp(scheme, SCHEME_FTP) == 0)
return (FTP_DEFAULT_PROXY_PORT);
@@ -203,7 +207,7 @@
* Create a connection for an existing descriptor.
*/
conn_t *
-_fetch_reopen(int sd)
+fetch_reopen(int sd)
{
conn_t *conn;
@@ -220,7 +224,7 @@
* Bump a connection's reference count.
*/
conn_t *
-_fetch_ref(conn_t *conn)
+fetch_ref(conn_t *conn)
{
++conn->ref;
@@ -232,7 +236,7 @@
* Bind a socket to a specific local address
*/
int
-_fetch_bind(int sd, int af, const char *addr)
+fetch_bind(int sd, int af, const char *addr)
{
struct addrinfo hints, *res, *res0;
int err;
@@ -254,7 +258,7 @@
* Establish a TCP connection to the specified port on the specified host.
*/
conn_t *
-_fetch_connect(const char *host, int port, int af, int verbose)
+fetch_connect(const char *host, int port, int af, int verbose)
{
conn_t *conn;
char pbuf[10];
@@ -265,7 +269,7 @@
DEBUG(fprintf(stderr, "---> %s:%d\n", host, port));
if (verbose)
- _fetch_info("looking up %s", host);
+ fetch_info("looking up %s", host);
/* look up host name and set up socket address structure */
snprintf(pbuf, sizeof(pbuf), "%d", port);
@@ -274,13 +278,13 @@
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((err = getaddrinfo(host, pbuf, &hints, &res0)) != 0) {
- _netdb_seterr(err);
+ netdb_seterr(err);
return (NULL);
}
bindaddr = getenv("FETCH_BIND_ADDRESS");
if (verbose)
- _fetch_info("connecting to %s:%d", host, port);
+ fetch_info("connecting to %s:%d", host, port);
/* try to connect */
for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) {
@@ -288,8 +292,8 @@
res->ai_protocol)) == -1)
continue;
if (bindaddr != NULL && *bindaddr != '\0' &&
- _fetch_bind(sd, res->ai_family, bindaddr) != 0) {
- _fetch_info("failed to bind to '%s'", bindaddr);
+ fetch_bind(sd, res->ai_family, bindaddr) != 0) {
+ fetch_info("failed to bind to '%s'", bindaddr);
close(sd);
continue;
}
@@ -299,12 +303,12 @@
}
freeaddrinfo(res0);
if (sd == -1) {
- _fetch_syserr();
+ fetch_syserr();
return (NULL);
}
- if ((conn = _fetch_reopen(sd)) == NULL) {
- _fetch_syserr();
+ if ((conn = fetch_reopen(sd)) == NULL) {
+ fetch_syserr();
close(sd);
}
return (conn);
@@ -315,7 +319,7 @@
* Enable SSL on a connection.
*/
int
-_fetch_ssl(conn_t *conn, int verbose)
+fetch_ssl(conn_t *conn, int verbose)
{
#ifdef WITH_SSL
@@ -373,9 +377,9 @@
* Read a character from a connection w/ timeout
*/
ssize_t
-_fetch_read(conn_t *conn, char *buf, size_t len)
+fetch_read(conn_t *conn, char *buf, size_t len)
{
- struct timeval now, timeout, wait;
+ struct timeval now, timeout, delta;
fd_set readfds;
ssize_t rlen, total;
int r;
@@ -391,23 +395,23 @@
while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) {
FD_SET(conn->sd, &readfds);
gettimeofday(&now, NULL);
- wait.tv_sec = timeout.tv_sec - now.tv_sec;
- wait.tv_usec = timeout.tv_usec - now.tv_usec;
- if (wait.tv_usec < 0) {
- wait.tv_usec += 1000000;
- wait.tv_sec--;
+ delta.tv_sec = timeout.tv_sec - now.tv_sec;
+ delta.tv_usec = timeout.tv_usec - now.tv_usec;
+ if (delta.tv_usec < 0) {
+ delta.tv_usec += 1000000;
+ delta.tv_sec--;
}
- if (wait.tv_sec < 0) {
+ if (delta.tv_sec < 0) {
errno = ETIMEDOUT;
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
errno = 0;
- r = select(conn->sd + 1, &readfds, NULL, NULL, &wait);
+ r = select(conn->sd + 1, &readfds, NULL, NULL, &delta);
if (r == -1) {
if (errno == EINTR && fetchRestartCalls)
continue;
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
}
@@ -438,7 +442,7 @@
#define MIN_BUF_SIZE 1024
int
-_fetch_getln(conn_t *conn)
+fetch_getln(conn_t *conn)
{
char *tmp;
size_t tmpsize;
@@ -457,7 +461,7 @@
conn->buflen = 0;
do {
- len = _fetch_read(conn, &c, 1);
+ len = fetch_read(conn, &c, 1);
if (len == -1)
return (-1);
if (len == 0)
@@ -485,13 +489,13 @@
* Write to a connection w/ timeout
*/
ssize_t
-_fetch_write(conn_t *conn, const char *buf, size_t len)
+fetch_write(conn_t *conn, const char *buf, size_t len)
{
struct iovec iov;
iov.iov_base = __DECONST(char *, buf);
iov.iov_len = len;
- return _fetch_writev(conn, &iov, 1);
+ return fetch_writev(conn, &iov, 1);
}
/*
@@ -499,9 +503,9 @@
* Note: can modify the iovec.
*/
ssize_t
-_fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt)
+fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt)
{
- struct timeval now, timeout, wait;
+ struct timeval now, timeout, delta;
fd_set writefds;
ssize_t wlen, total;
int r;
@@ -517,19 +521,19 @@
while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) {
FD_SET(conn->sd, &writefds);
gettimeofday(&now, NULL);
- wait.tv_sec = timeout.tv_sec - now.tv_sec;
- wait.tv_usec = timeout.tv_usec - now.tv_usec;
- if (wait.tv_usec < 0) {
- wait.tv_usec += 1000000;
- wait.tv_sec--;
+ delta.tv_sec = timeout.tv_sec - now.tv_sec;
+ delta.tv_usec = timeout.tv_usec - now.tv_usec;
+ if (delta.tv_usec < 0) {
+ delta.tv_usec += 1000000;
+ delta.tv_sec--;
}
- if (wait.tv_sec < 0) {
+ if (delta.tv_sec < 0) {
errno = ETIMEDOUT;
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
errno = 0;
- r = select(conn->sd + 1, NULL, &writefds, NULL, &wait);
+ r = select(conn->sd + 1, NULL, &writefds, NULL, &delta);
if (r == -1) {
if (errno == EINTR && fetchRestartCalls)
continue;
@@ -547,7 +551,7 @@
if (wlen == 0) {
/* we consider a short write a failure */
errno = EPIPE;
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
if (wlen < 0) {
@@ -574,7 +578,7 @@
* Write a line of text to a connection w/ timeout
*/
int
-_fetch_putln(conn_t *conn, const char *str, size_t len)
+fetch_putln(conn_t *conn, const char *str, size_t len)
{
struct iovec iov[2];
int ret;
@@ -585,9 +589,9 @@
iov[1].iov_base = __DECONST(char *, ENDL);
iov[1].iov_len = sizeof(ENDL);
if (len == 0)
- ret = _fetch_writev(conn, &iov[1], 1);
+ ret = fetch_writev(conn, &iov[1], 1);
else
- ret = _fetch_writev(conn, iov, 2);
+ ret = fetch_writev(conn, iov, 2);
if (ret == -1)
return (-1);
return (0);
@@ -598,7 +602,7 @@
* Close connection
*/
int
-_fetch_close(conn_t *conn)
+fetch_close(conn_t *conn)
{
int ret;
@@ -614,7 +618,7 @@
/*** Directory-related utility functions *************************************/
int
-_fetch_add_entry(struct url_ent **p, int *size, int *len,
+fetch_add_entry(struct url_ent **p, int *size, int *len,
const char *name, struct url_stat *us)
{
struct url_ent *tmp;
@@ -628,7 +632,7 @@
tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p));
if (tmp == NULL) {
errno = ENOMEM;
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
*size = (*size * 2 + 1);
@@ -637,7 +641,7 @@
tmp = *p + *len;
snprintf(tmp->name, PATH_MAX, "%s", name);
- bcopy(us, &tmp->stat, sizeof(*us));
+ memcpy(&tmp->stat, us, sizeof(*us));
(*len)++;
(++tmp)->name[0] = 0;
@@ -649,11 +653,11 @@
/*** Authentication-related utility functions ********************************/
static const char *
-_fetch_read_word(FILE *f)
+fetch_read_word(FILE *f)
{
static char word[1024];
- if (fscanf(f, " %1024s ", word) != 1)
+ if (fscanf(f, " %1023s ", word) != 1)
return (NULL);
return (word);
}
@@ -662,7 +666,7 @@
* Get authentication data for a URL from .netrc
*/
int
-_fetch_netrc_auth(struct url *url)
+fetch_netrc_auth(struct url *url)
{
char fn[PATH_MAX];
const char *word;
@@ -671,7 +675,7 @@
if ((p = getenv("NETRC")) != NULL) {
if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
- _fetch_info("$NETRC specifies a file name "
+ fetch_info("$NETRC specifies a file name "
"longer than PATH_MAX");
return (-1);
}
@@ -689,39 +693,39 @@
if ((f = fopen(fn, "r")) == NULL)
return (-1);
- while ((word = _fetch_read_word(f)) != NULL) {
+ while ((word = fetch_read_word(f)) != NULL) {
if (strcmp(word, "default") == 0) {
- DEBUG(_fetch_info("Using default .netrc settings"));
+ DEBUG(fetch_info("Using default .netrc settings"));
break;
}
if (strcmp(word, "machine") == 0 &&
- (word = _fetch_read_word(f)) != NULL &&
+ (word = fetch_read_word(f)) != NULL &&
strcasecmp(word, url->host) == 0) {
- DEBUG(_fetch_info("Using .netrc settings for %s", word));
+ DEBUG(fetch_info("Using .netrc settings for %s", word));
break;
}
}
if (word == NULL)
goto ferr;
- while ((word = _fetch_read_word(f)) != NULL) {
+ while ((word = fetch_read_word(f)) != NULL) {
if (strcmp(word, "login") == 0) {
- if ((word = _fetch_read_word(f)) == NULL)
+ if ((word = fetch_read_word(f)) == NULL)
goto ferr;
if (snprintf(url->user, sizeof(url->user),
"%s", word) > (int)sizeof(url->user)) {
- _fetch_info("login name in .netrc is too long");
+ fetch_info("login name in .netrc is too long");
url->user[0] = '\0';
}
} else if (strcmp(word, "password") == 0) {
- if ((word = _fetch_read_word(f)) == NULL)
+ if ((word = fetch_read_word(f)) == NULL)
goto ferr;
if (snprintf(url->pwd, sizeof(url->pwd),
"%s", word) > (int)sizeof(url->pwd)) {
- _fetch_info("password in .netrc is too long");
+ fetch_info("password in .netrc is too long");
url->pwd[0] = '\0';
}
} else if (strcmp(word, "account") == 0) {
- if ((word = _fetch_read_word(f)) == NULL)
+ if ((word = fetch_read_word(f)) == NULL)
goto ferr;
/* XXX not supported! */
} else {
@@ -734,3 +738,51 @@
fclose(f);
return (-1);
}
+
+/*
+ * The no_proxy environment variable specifies a set of domains for
+ * which the proxy should not be consulted; the contents is a comma-,
+ * or space-separated list of domain names. A single asterisk will
+ * override all proxy variables and no transactions will be proxied
+ * (for compatability with lynx and curl, see the discussion at
+ * <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>).
+ */
+int
+fetch_no_proxy_match(const char *host)
+{
+ const char *no_proxy, *p, *q;
+ size_t h_len, d_len;
+
+ if ((no_proxy = getenv("NO_PROXY")) == NULL &&
+ (no_proxy = getenv("no_proxy")) == NULL)
+ return (0);
+
+ /* asterisk matches any hostname */
+ if (strcmp(no_proxy, "*") == 0)
+ return (1);
+
+ h_len = strlen(host);
+ p = no_proxy;
+ do {
+ /* position p at the beginning of a domain suffix */
+ while (*p == ',' || isspace((unsigned char)*p))
+ p++;
+
+ /* position q at the first separator character */
+ for (q = p; *q; ++q)
+ if (*q == ',' || isspace((unsigned char)*q))
+ break;
+
+ d_len = q - p;
+ if (d_len > 0 && h_len > d_len &&
+ strncasecmp(host + h_len - d_len,
+ p, d_len) == 0) {
+ /* domain name matches */
+ return (1);
+ }
+
+ p = q + 1;
+ } while (*q);
+
+ return (0);
+}
Index: http.errors
===================================================================
RCS file: /home/cvs/src/lib/libfetch/http.errors,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/http.errors -L lib/libfetch/http.errors -u -r1.1.1.1 -r1.2
--- lib/libfetch/http.errors
+++ lib/libfetch/http.errors
@@ -1,3 +1,4 @@
+# $MidnightBSD$
# $FreeBSD: src/lib/libfetch/http.errors,v 1.5 2001/05/23 18:52:02 des Exp $
#
# This list is taken from RFC 2068.
Index: common.h
===================================================================
RCS file: /home/cvs/src/lib/libfetch/common.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/common.h -L lib/libfetch/common.h -u -r1.1.1.1 -r1.2
--- lib/libfetch/common.h
+++ lib/libfetch/common.h
@@ -25,7 +25,8 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/lib/libfetch/common.h,v 1.28 2004/09/21 18:35:20 des Exp $
+ * $MidnightBSD$
+ * $FreeBSD: src/lib/libfetch/common.h,v 1.30 2007/12/18 11:03:07 des Exp $
*/
#ifndef _COMMON_H_INCLUDED
@@ -68,33 +69,34 @@
const char *string;
};
-/* for _fetch_writev */
+/* for fetch_writev */
struct iovec;
-void _fetch_seterr(struct fetcherr *, int);
-void _fetch_syserr(void);
-void _fetch_info(const char *, ...);
-int _fetch_default_port(const char *);
-int _fetch_default_proxy_port(const char *);
-int _fetch_bind(int, int, const char *);
-conn_t *_fetch_connect(const char *, int, int, int);
-conn_t *_fetch_reopen(int);
-conn_t *_fetch_ref(conn_t *);
-int _fetch_ssl(conn_t *, int);
-ssize_t _fetch_read(conn_t *, char *, size_t);
-int _fetch_getln(conn_t *);
-ssize_t _fetch_write(conn_t *, const char *, size_t);
-ssize_t _fetch_writev(conn_t *, struct iovec *, int);
-int _fetch_putln(conn_t *, const char *, size_t);
-int _fetch_close(conn_t *);
-int _fetch_add_entry(struct url_ent **, int *, int *,
+void fetch_seterr(struct fetcherr *, int);
+void fetch_syserr(void);
+void fetch_info(const char *, ...);
+int fetch_default_port(const char *);
+int fetch_default_proxy_port(const char *);
+int fetch_bind(int, int, const char *);
+conn_t *fetch_connect(const char *, int, int, int);
+conn_t *fetch_reopen(int);
+conn_t *fetch_ref(conn_t *);
+int fetch_ssl(conn_t *, int);
+ssize_t fetch_read(conn_t *, char *, size_t);
+int fetch_getln(conn_t *);
+ssize_t fetch_write(conn_t *, const char *, size_t);
+ssize_t fetch_writev(conn_t *, struct iovec *, int);
+int fetch_putln(conn_t *, const char *, size_t);
+int fetch_close(conn_t *);
+int fetch_add_entry(struct url_ent **, int *, int *,
const char *, struct url_stat *);
-int _fetch_netrc_auth(struct url *url);
+int fetch_netrc_auth(struct url *url);
+int fetch_no_proxy_match(const char *);
-#define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n)
-#define _http_seterr(n) _fetch_seterr(_http_errlist, n)
-#define _netdb_seterr(n) _fetch_seterr(_netdb_errlist, n)
-#define _url_seterr(n) _fetch_seterr(_url_errlist, n)
+#define ftp_seterr(n) fetch_seterr(ftp_errlist, n)
+#define http_seterr(n) fetch_seterr(http_errlist, n)
+#define netdb_seterr(n) fetch_seterr(netdb_errlist, n)
+#define url_seterr(n) fetch_seterr(url_errlist, n)
#ifndef NDEBUG
#define DEBUG(x) do { if (fetchDebug) { x; } } while (0)
@@ -103,7 +105,7 @@
#endif
/*
- * I don't really like exporting _http_request() and _ftp_request(),
+ * I don't really like exporting http_request() and ftp_request(),
* but the HTTP and FTP code occasionally needs to cross-call
* eachother, and this saves me from adding a lot of special-case code
* to handle those cases.
@@ -111,9 +113,9 @@
* Note that _*_request() free purl, which is way ugly but saves us a
* whole lot of trouble.
*/
-FILE *_http_request(struct url *, const char *,
+FILE *http_request(struct url *, const char *,
struct url_stat *, struct url *, const char *);
-FILE *_ftp_request(struct url *, const char *,
+FILE *ftp_request(struct url *, const char *,
struct url_stat *, struct url *, const char *);
/*
Index: http.c
===================================================================
RCS file: /home/cvs/src/lib/libfetch/http.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/http.c -L lib/libfetch/http.c -u -r1.1.1.1 -r1.2
--- lib/libfetch/http.c
+++ lib/libfetch/http.c
@@ -24,10 +24,12 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libfetch/http.c,v 1.84 2008/02/08 09:48:48 des Exp $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libfetch/http.c,v 1.76.2.1 2005/12/14 09:10:13 des Exp $");
+__MBSDID("$MidnightBSD$");
/*
* The following copyright applies to the base64 code:
@@ -92,6 +94,7 @@
#define HTTP_MOVED_PERM 301
#define HTTP_MOVED_TEMP 302
#define HTTP_SEE_OTHER 303
+#define HTTP_TEMP_REDIRECT 307
#define HTTP_NEED_AUTH 401
#define HTTP_NEED_PROXY_AUTH 407
#define HTTP_BAD_RANGE 416
@@ -99,6 +102,7 @@
#define HTTP_REDIRECT(xyz) ((xyz) == HTTP_MOVED_PERM \
|| (xyz) == HTTP_MOVED_TEMP \
+ || (xyz) == HTTP_TEMP_REDIRECT \
|| (xyz) == HTTP_SEE_OTHER)
#define HTTP_ERROR(xyz) ((xyz) > 400 && (xyz) < 599)
@@ -128,27 +132,27 @@
* Get next chunk header
*/
static int
-_http_new_chunk(struct httpio *io)
+http_new_chunk(struct httpio *io)
{
char *p;
- if (_fetch_getln(io->conn) == -1)
+ if (fetch_getln(io->conn) == -1)
return (-1);
- if (io->conn->buflen < 2 || !ishexnumber(*io->conn->buf))
+ if (io->conn->buflen < 2 || !isxdigit((unsigned char)*io->conn->buf))
return (-1);
- for (p = io->conn->buf; *p && !isspace(*p); ++p) {
+ for (p = io->conn->buf; *p && !isspace((unsigned char)*p); ++p) {
if (*p == ';')
break;
- if (!ishexnumber(*p))
+ if (!isxdigit((unsigned char)*p))
return (-1);
- if (isdigit(*p)) {
+ if (isdigit((unsigned char)*p)) {
io->chunksize = io->chunksize * 16 +
*p - '0';
} else {
io->chunksize = io->chunksize * 16 +
- 10 + tolower(*p) - 'a';
+ 10 + tolower((unsigned char)*p) - 'a';
}
}
@@ -171,7 +175,7 @@
* Grow the input buffer to at least len bytes
*/
static inline int
-_http_growbuf(struct httpio *io, size_t len)
+http_growbuf(struct httpio *io, size_t len)
{
char *tmp;
@@ -189,7 +193,7 @@
* Fill the input buffer, do chunk decoding on the fly
*/
static int
-_http_fillbuf(struct httpio *io, size_t len)
+http_fillbuf(struct httpio *io, size_t len)
{
if (io->error)
return (-1);
@@ -197,9 +201,9 @@
return (0);
if (io->chunked == 0) {
- if (_http_growbuf(io, len) == -1)
+ if (http_growbuf(io, len) == -1)
return (-1);
- if ((io->buflen = _fetch_read(io->conn, io->buf, len)) == -1) {
+ if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) {
io->error = 1;
return (-1);
}
@@ -208,7 +212,7 @@
}
if (io->chunksize == 0) {
- switch (_http_new_chunk(io)) {
+ switch (http_new_chunk(io)) {
case -1:
io->error = 1;
return (-1);
@@ -220,9 +224,9 @@
if (len > io->chunksize)
len = io->chunksize;
- if (_http_growbuf(io, len) == -1)
+ if (http_growbuf(io, len) == -1)
return (-1);
- if ((io->buflen = _fetch_read(io->conn, io->buf, len)) == -1) {
+ if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) {
io->error = 1;
return (-1);
}
@@ -231,7 +235,7 @@
if (io->chunksize == 0) {
char endl[2];
- if (_fetch_read(io->conn, endl, 2) != 2 ||
+ if (fetch_read(io->conn, endl, 2) != 2 ||
endl[0] != '\r' || endl[1] != '\n')
return (-1);
}
@@ -245,7 +249,7 @@
* Read function
*/
static int
-_http_readfn(void *v, char *buf, int len)
+http_readfn(void *v, char *buf, int len)
{
struct httpio *io = (struct httpio *)v;
int l, pos;
@@ -258,12 +262,12 @@
for (pos = 0; len > 0; pos += l, len -= l) {
/* empty buffer */
if (!io->buf || io->bufpos == io->buflen)
- if (_http_fillbuf(io, len) < 1)
+ if (http_fillbuf(io, len) < 1)
break;
l = io->buflen - io->bufpos;
if (len < l)
l = len;
- bcopy(io->buf + io->bufpos, buf + pos, l);
+ memcpy(buf + pos, io->buf + io->bufpos, l);
io->bufpos += l;
}
@@ -276,23 +280,23 @@
* Write function
*/
static int
-_http_writefn(void *v, const char *buf, int len)
+http_writefn(void *v, const char *buf, int len)
{
struct httpio *io = (struct httpio *)v;
- return (_fetch_write(io->conn, buf, len));
+ return (fetch_write(io->conn, buf, len));
}
/*
* Close function
*/
static int
-_http_closefn(void *v)
+http_closefn(void *v)
{
struct httpio *io = (struct httpio *)v;
int r;
- r = _fetch_close(io->conn);
+ r = fetch_close(io->conn);
if (io->buf)
free(io->buf);
free(io);
@@ -303,20 +307,20 @@
* Wrap a file descriptor up
*/
static FILE *
-_http_funopen(conn_t *conn, int chunked)
+http_funopen(conn_t *conn, int chunked)
{
struct httpio *io;
FILE *f;
if ((io = calloc(1, sizeof(*io))) == NULL) {
- _fetch_syserr();
+ fetch_syserr();
return (NULL);
}
io->conn = conn;
io->chunked = chunked;
- f = funopen(io, _http_readfn, _http_writefn, NULL, _http_closefn);
+ f = funopen(io, http_readfn, http_writefn, NULL, http_closefn);
if (f == NULL) {
- _fetch_syserr();
+ fetch_syserr();
free(io);
return (NULL);
}
@@ -360,7 +364,7 @@
* Send a formatted line; optionally echo to terminal
*/
static int
-_http_cmd(conn_t *conn, const char *fmt, ...)
+http_cmd(conn_t *conn, const char *fmt, ...)
{
va_list ap;
size_t len;
@@ -373,15 +377,15 @@
if (msg == NULL) {
errno = ENOMEM;
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
- r = _fetch_putln(conn, msg, len);
+ r = fetch_putln(conn, msg, len);
free(msg);
if (r == -1) {
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
@@ -392,11 +396,11 @@
* Get and parse status line
*/
static int
-_http_get_reply(conn_t *conn)
+http_get_reply(conn_t *conn)
{
char *p;
- if (_fetch_getln(conn) == -1)
+ if (fetch_getln(conn) == -1)
return (-1);
/*
* A valid status line looks like "HTTP/m.n xyz reason" where m
@@ -415,7 +419,10 @@
return (HTTP_PROTOCOL_ERROR);
p += 4;
}
- if (*p != ' ' || !isdigit(p[1]) || !isdigit(p[2]) || !isdigit(p[3]))
+ if (*p != ' ' ||
+ !isdigit((unsigned char)p[1]) ||
+ !isdigit((unsigned char)p[2]) ||
+ !isdigit((unsigned char)p[3]))
return (HTTP_PROTOCOL_ERROR);
conn->err = (p[1] - '0') * 100 + (p[2] - '0') * 10 + (p[3] - '0');
@@ -427,13 +434,14 @@
* to the beginning of the value.
*/
static const char *
-_http_match(const char *str, const char *hdr)
+http_match(const char *str, const char *hdr)
{
- while (*str && *hdr && tolower(*str++) == tolower(*hdr++))
+ while (*str && *hdr &&
+ tolower((unsigned char)*str++) == tolower((unsigned char)*hdr++))
/* nothing */;
if (*str || *hdr != ':')
return (NULL);
- while (*hdr && isspace(*++hdr))
+ while (*hdr && isspace((unsigned char)*++hdr))
/* nothing */;
return (hdr);
}
@@ -442,13 +450,13 @@
* Get the next header and return the appropriate symbolic code.
*/
static hdr_t
-_http_next_header(conn_t *conn, const char **p)
+http_next_header(conn_t *conn, const char **p)
{
int i;
- if (_fetch_getln(conn) == -1)
+ if (fetch_getln(conn) == -1)
return (hdr_syserror);
- while (conn->buflen && isspace(conn->buf[conn->buflen - 1]))
+ while (conn->buflen && isspace((unsigned char)conn->buf[conn->buflen - 1]))
conn->buflen--;
conn->buf[conn->buflen] = '\0';
if (conn->buflen == 0)
@@ -460,7 +468,7 @@
* characters except "()<>@,;:\\\"{}".
*/
for (i = 0; hdr_names[i].num != hdr_unknown; i++)
- if ((*p = _http_match(hdr_names[i].name, conn->buf)) != NULL)
+ if ((*p = http_match(hdr_names[i].name, conn->buf)) != NULL)
return (hdr_names[i].num);
return (hdr_unknown);
}
@@ -469,7 +477,7 @@
* Parse a last-modified header
*/
static int
-_http_parse_mtime(const char *p, time_t *mtime)
+http_parse_mtime(const char *p, time_t *mtime)
{
char locale[64], *r;
struct tm tm;
@@ -493,11 +501,11 @@
* Parse a content-length header
*/
static int
-_http_parse_length(const char *p, off_t *length)
+http_parse_length(const char *p, off_t *length)
{
off_t len;
- for (len = 0; *p && isdigit(*p); ++p)
+ for (len = 0; *p && isdigit((unsigned char)*p); ++p)
len = len * 10 + (*p - '0');
if (*p)
return (-1);
@@ -511,7 +519,7 @@
* Parse a content-range header
*/
static int
-_http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size)
+http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size)
{
off_t first, last, len;
@@ -522,16 +530,16 @@
first = last = -1;
++p;
} else {
- for (first = 0; *p && isdigit(*p); ++p)
+ for (first = 0; *p && isdigit((unsigned char)*p); ++p)
first = first * 10 + *p - '0';
if (*p != '-')
return (-1);
- for (last = 0, ++p; *p && isdigit(*p); ++p)
+ for (last = 0, ++p; *p && isdigit((unsigned char)*p); ++p)
last = last * 10 + *p - '0';
}
if (first > last || *p != '/')
return (-1);
- for (len = 0, ++p; *p && isdigit(*p); ++p)
+ for (len = 0, ++p; *p && isdigit((unsigned char)*p); ++p)
len = len * 10 + *p - '0';
if (*p || len < last - first + 1)
return (-1);
@@ -558,7 +566,7 @@
* Base64 encoding
*/
static char *
-_http_base64(const char *src)
+http_base64(const char *src)
{
static const char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -614,7 +622,7 @@
* Encode username and password
*/
static int
-_http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd)
+http_basic_auth(conn_t *conn, const char *hdr, const char *usr, const char *pwd)
{
char *upw, *auth;
int r;
@@ -623,11 +631,11 @@
DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd));
if (asprintf(&upw, "%s:%s", usr, pwd) == -1)
return (-1);
- auth = _http_base64(upw);
+ auth = http_base64(upw);
free(upw);
if (auth == NULL)
return (-1);
- r = _http_cmd(conn, "%s: Basic %s", hdr, auth);
+ r = http_cmd(conn, "%s: Basic %s", hdr, auth);
free(auth);
return (r);
}
@@ -636,7 +644,7 @@
* Send an authorization header
*/
static int
-_http_authorize(conn_t *conn, const char *hdr, const char *p)
+http_authorize(conn_t *conn, const char *hdr, const char *p)
{
/* basic authorization */
if (strncasecmp(p, "basic:", 6) == 0) {
@@ -653,7 +661,7 @@
user = str;
pwd = strchr(str, ':');
*pwd++ = '\0';
- r = _http_basic_auth(conn, hdr, user, pwd);
+ r = http_basic_auth(conn, hdr, user, pwd);
free(str);
return (r);
}
@@ -669,7 +677,7 @@
* Connect to the correct HTTP server or proxy.
*/
static conn_t *
-_http_connect(struct url *URL, struct url *purl, const char *flags)
+http_connect(struct url *URL, struct url *purl, const char *flags)
{
conn_t *conn;
int verbose;
@@ -697,15 +705,15 @@
return (NULL);
}
- if ((conn = _fetch_connect(URL->host, URL->port, af, verbose)) == NULL)
- /* _fetch_connect() has already set an error code */
+ if ((conn = fetch_connect(URL->host, URL->port, af, verbose)) == NULL)
+ /* fetch_connect() has already set an error code */
return (NULL);
if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
- _fetch_ssl(conn, verbose) == -1) {
- _fetch_close(conn);
+ fetch_ssl(conn, verbose) == -1) {
+ fetch_close(conn);
/* grrr */
errno = EAUTH;
- _fetch_syserr();
+ fetch_syserr();
return (NULL);
}
@@ -716,19 +724,21 @@
}
static struct url *
-_http_get_proxy(const char *flags)
+http_get_proxy(struct url * url, const char *flags)
{
struct url *purl;
char *p;
if (flags != NULL && strchr(flags, 'd') != NULL)
return (NULL);
+ if (fetch_no_proxy_match(url->host))
+ return (NULL);
if (((p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) &&
*p && (purl = fetchParseURL(p))) {
if (!*purl->scheme)
strcpy(purl->scheme, SCHEME_HTTP);
if (!purl->port)
- purl->port = _fetch_default_proxy_port(purl->scheme);
+ purl->port = fetch_default_proxy_port(purl->scheme);
if (strcasecmp(purl->scheme, SCHEME_HTTP) == 0)
return (purl);
fetchFreeURL(purl);
@@ -737,7 +747,7 @@
}
static void
-_http_print_html(FILE *out, FILE *in)
+http_print_html(FILE *out, FILE *in)
{
size_t len;
char *line, *p, *q;
@@ -745,7 +755,7 @@
comment = tag = 0;
while ((line = fgetln(in, &len)) != NULL) {
- while (len && isspace(line[len - 1]))
+ while (len && isspace((unsigned char)line[len - 1]))
--len;
for (p = q = line; q < line + len; ++q) {
if (comment && *q == '-') {
@@ -786,7 +796,7 @@
* XXX off into a separate function.
*/
FILE *
-_http_request(struct url *URL, const char *op, struct url_stat *us,
+http_request(struct url *URL, const char *op, struct url_stat *us,
struct url *purl, const char *flags)
{
conn_t *conn;
@@ -829,18 +839,18 @@
/* check port */
if (!url->port)
- url->port = _fetch_default_port(url->scheme);
+ url->port = fetch_default_port(url->scheme);
/* were we redirected to an FTP URL? */
if (purl == NULL && strcmp(url->scheme, SCHEME_FTP) == 0) {
if (strcmp(op, "GET") == 0)
- return (_ftp_request(url, "RETR", us, purl, flags));
+ return (ftp_request(url, "RETR", us, purl, flags));
else if (strcmp(op, "HEAD") == 0)
- return (_ftp_request(url, "STAT", us, purl, flags));
+ return (ftp_request(url, "STAT", us, purl, flags));
}
/* connect to server or proxy */
- if ((conn = _http_connect(url, purl, flags)) == NULL)
+ if ((conn = http_connect(url, purl, flags)) == NULL)
goto ouch;
host = url->host;
@@ -850,7 +860,7 @@
host = hbuf;
}
#endif
- if (url->port != _fetch_default_port(url->scheme)) {
+ if (url->port != fetch_default_port(url->scheme)) {
if (host != hbuf) {
strcpy(hbuf, host);
host = hbuf;
@@ -861,38 +871,38 @@
/* send request */
if (verbose)
- _fetch_info("requesting %s://%s%s",
+ fetch_info("requesting %s://%s%s",
url->scheme, host, url->doc);
if (purl) {
- _http_cmd(conn, "%s %s://%s%s HTTP/1.1",
+ http_cmd(conn, "%s %s://%s%s HTTP/1.1",
op, url->scheme, host, url->doc);
} else {
- _http_cmd(conn, "%s %s HTTP/1.1",
+ http_cmd(conn, "%s %s HTTP/1.1",
op, url->doc);
}
/* virtual host */
- _http_cmd(conn, "Host: %s", host);
+ http_cmd(conn, "Host: %s", host);
/* proxy authorization */
if (purl) {
if (*purl->user || *purl->pwd)
- _http_basic_auth(conn, "Proxy-Authorization",
+ http_basic_auth(conn, "Proxy-Authorization",
purl->user, purl->pwd);
else if ((p = getenv("HTTP_PROXY_AUTH")) != NULL && *p != '\0')
- _http_authorize(conn, "Proxy-Authorization", p);
+ http_authorize(conn, "Proxy-Authorization", p);
}
/* server authorization */
if (need_auth || *url->user || *url->pwd) {
if (*url->user || *url->pwd)
- _http_basic_auth(conn, "Authorization", url->user, url->pwd);
+ http_basic_auth(conn, "Authorization", url->user, url->pwd);
else if ((p = getenv("HTTP_AUTH")) != NULL && *p != '\0')
- _http_authorize(conn, "Authorization", p);
+ http_authorize(conn, "Authorization", p);
else if (fetchAuthMethod && fetchAuthMethod(url) == 0) {
- _http_basic_auth(conn, "Authorization", url->user, url->pwd);
+ http_basic_auth(conn, "Authorization", url->user, url->pwd);
} else {
- _http_seterr(HTTP_NEED_AUTH);
+ http_seterr(HTTP_NEED_AUTH);
goto ouch;
}
}
@@ -900,19 +910,19 @@
/* other headers */
if ((p = getenv("HTTP_REFERER")) != NULL && *p != '\0') {
if (strcasecmp(p, "auto") == 0)
- _http_cmd(conn, "Referer: %s://%s%s",
+ http_cmd(conn, "Referer: %s://%s%s",
url->scheme, host, url->doc);
else
- _http_cmd(conn, "Referer: %s", p);
+ http_cmd(conn, "Referer: %s", p);
}
if ((p = getenv("HTTP_USER_AGENT")) != NULL && *p != '\0')
- _http_cmd(conn, "User-Agent: %s", p);
+ http_cmd(conn, "User-Agent: %s", p);
else
- _http_cmd(conn, "User-Agent: %s " _LIBFETCH_VER, getprogname());
+ http_cmd(conn, "User-Agent: %s " _LIBFETCH_VER, getprogname());
if (url->offset > 0)
- _http_cmd(conn, "Range: bytes=%lld-", (long long)url->offset);
- _http_cmd(conn, "Connection: close");
- _http_cmd(conn, "");
+ http_cmd(conn, "Range: bytes=%lld-", (long long)url->offset);
+ http_cmd(conn, "Connection: close");
+ http_cmd(conn, "");
/*
* Force the queued request to be dispatched. Normally, one
@@ -929,7 +939,7 @@
sizeof(val));
/* get reply */
- switch (_http_get_reply(conn)) {
+ switch (http_get_reply(conn)) {
case HTTP_OK:
case HTTP_PARTIAL:
/* fine */
@@ -948,12 +958,12 @@
* We already sent out authorization code,
* so there's nothing more we can do.
*/
- _http_seterr(conn->err);
+ http_seterr(conn->err);
goto ouch;
}
/* try again, but send the password this time */
if (verbose)
- _fetch_info("server requires authorization");
+ fetch_info("server requires authorization");
break;
case HTTP_NEED_PROXY_AUTH:
/*
@@ -961,7 +971,7 @@
* our proxy authorization code, so there's
* nothing more we can do.
*/
- _http_seterr(conn->err);
+ http_seterr(conn->err);
goto ouch;
case HTTP_BAD_RANGE:
/*
@@ -973,10 +983,10 @@
case HTTP_PROTOCOL_ERROR:
/* fall through */
case -1:
- _fetch_syserr();
+ fetch_syserr();
goto ouch;
default:
- _http_seterr(conn->err);
+ http_seterr(conn->err);
if (!verbose)
goto ouch;
/* fall through so we can get the full error message */
@@ -984,21 +994,21 @@
/* get headers */
do {
- switch ((h = _http_next_header(conn, &p))) {
+ switch ((h = http_next_header(conn, &p))) {
case hdr_syserror:
- _fetch_syserr();
+ fetch_syserr();
goto ouch;
case hdr_error:
- _http_seterr(HTTP_PROTOCOL_ERROR);
+ http_seterr(HTTP_PROTOCOL_ERROR);
goto ouch;
case hdr_content_length:
- _http_parse_length(p, &clength);
+ http_parse_length(p, &clength);
break;
case hdr_content_range:
- _http_parse_range(p, &offset, &length, &size);
+ http_parse_range(p, &offset, &length, &size);
break;
case hdr_last_modified:
- _http_parse_mtime(p, &mtime);
+ http_parse_mtime(p, &mtime);
break;
case hdr_location:
if (!HTTP_REDIRECT(conn->err))
@@ -1006,7 +1016,7 @@
if (new)
free(new);
if (verbose)
- _fetch_info("%d redirect to %s", conn->err, p);
+ fetch_info("%d redirect to %s", conn->err, p);
if (*p == '/')
/* absolute path */
new = fetchMakeURL(url->scheme, url->host, url->port, p,
@@ -1046,7 +1056,7 @@
if (conn->err == HTTP_NEED_AUTH) {
e = conn->err;
need_auth = 1;
- _fetch_close(conn);
+ fetch_close(conn);
conn = NULL;
continue;
}
@@ -1059,7 +1069,7 @@
conn->err = HTTP_OK;
break;
} else {
- _http_seterr(conn->err);
+ http_seterr(conn->err);
goto ouch;
}
}
@@ -1071,7 +1081,7 @@
/* all other cases: we got a redirect */
e = conn->err;
need_auth = 0;
- _fetch_close(conn);
+ fetch_close(conn);
conn = NULL;
if (!new) {
DEBUG(fprintf(stderr, "redirect with no new location\n"));
@@ -1084,7 +1094,7 @@
/* we failed, or ran out of retries */
if (conn == NULL) {
- _http_seterr(e);
+ http_seterr(e);
goto ouch;
}
@@ -1095,7 +1105,7 @@
/* check for inconsistencies */
if (clength != -1 && length != -1 && clength != length) {
- _http_seterr(HTTP_PROTOCOL_ERROR);
+ http_seterr(HTTP_PROTOCOL_ERROR);
goto ouch;
}
if (clength == -1)
@@ -1103,7 +1113,7 @@
if (clength != -1)
length = offset + clength;
if (length != -1 && size != -1 && length != size) {
- _http_seterr(HTTP_PROTOCOL_ERROR);
+ http_seterr(HTTP_PROTOCOL_ERROR);
goto ouch;
}
if (size == -1)
@@ -1117,7 +1127,7 @@
/* too far? */
if (URL->offset > 0 && offset > URL->offset) {
- _http_seterr(HTTP_PROTOCOL_ERROR);
+ http_seterr(HTTP_PROTOCOL_ERROR);
goto ouch;
}
@@ -1126,8 +1136,8 @@
URL->length = clength;
/* wrap it up in a FILE */
- if ((f = _http_funopen(conn, chunked)) == NULL) {
- _fetch_syserr();
+ if ((f = http_funopen(conn, chunked)) == NULL) {
+ fetch_syserr();
goto ouch;
}
@@ -1137,7 +1147,7 @@
fetchFreeURL(purl);
if (HTTP_ERROR(conn->err)) {
- _http_print_html(stderr, f);
+ http_print_html(stderr, f);
fclose(f);
f = NULL;
}
@@ -1150,7 +1160,7 @@
if (purl)
fetchFreeURL(purl);
if (conn != NULL)
- _fetch_close(conn);
+ fetch_close(conn);
return (NULL);
}
@@ -1165,7 +1175,7 @@
FILE *
fetchXGetHTTP(struct url *URL, struct url_stat *us, const char *flags)
{
- return (_http_request(URL, "GET", us, _http_get_proxy(flags), flags));
+ return (http_request(URL, "GET", us, http_get_proxy(URL, flags), flags));
}
/*
@@ -1195,7 +1205,7 @@
{
FILE *f;
- f = _http_request(URL, "HEAD", us, _http_get_proxy(flags), flags);
+ f = http_request(URL, "HEAD", us, http_get_proxy(URL, flags), flags);
if (f == NULL)
return (-1);
fclose(f);
Index: ftp.errors
===================================================================
RCS file: /home/cvs/src/lib/libfetch/ftp.errors,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/ftp.errors -L lib/libfetch/ftp.errors -u -r1.1.1.1 -r1.2
--- lib/libfetch/ftp.errors
+++ lib/libfetch/ftp.errors
@@ -1,3 +1,4 @@
+# $MidnightBSD$
# $FreeBSD: src/lib/libfetch/ftp.errors,v 1.6 2002/10/30 06:06:16 des Exp $
#
# This list is taken from RFC 959.
Index: Makefile
===================================================================
RCS file: /home/cvs/src/lib/libfetch/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/Makefile -L lib/libfetch/Makefile -u -r1.1.1.1 -r1.2
--- lib/libfetch/Makefile
+++ lib/libfetch/Makefile
@@ -1,3 +1,4 @@
+# $MidnightBSD$
# $FreeBSD: src/lib/libfetch/Makefile,v 1.44.2.1 2005/07/22 17:29:05 kensmith Exp $
LIB= fetch
@@ -15,14 +16,16 @@
LDADD= -lssl -lcrypto
.endif
+CFLAGS+= -DFTP_COMBINE_CWDS
+
CSTD?= c99
WARNS?= 2
SHLIB_MAJOR= 4
-ftperr.h: ftp.errors
- @echo "static struct fetcherr _ftp_errlist[] = {" > ${.TARGET}
- @cat ${.ALLSRC} \
+ftperr.h: ftp.errors ${.CURDIR}/Makefile
+ @echo "static struct fetcherr ftp_errlist[] = {" > ${.TARGET}
+ @cat ${.CURDIR}/ftp.errors \
| grep -v ^# \
| sort \
| while read NUM CAT STRING; do \
@@ -31,9 +34,9 @@
@echo " { -1, FETCH_UNKNOWN, \"Unknown FTP error\" }" >> ${.TARGET}
@echo "};" >> ${.TARGET}
-httperr.h: http.errors
- @echo "static struct fetcherr _http_errlist[] = {" > ${.TARGET}
- @cat ${.ALLSRC} \
+httperr.h: http.errors ${.CURDIR}/Makefile
+ @echo "static struct fetcherr http_errlist[] = {" > ${.TARGET}
+ @cat ${.CURDIR}/http.errors \
| grep -v ^# \
| sort \
| while read NUM CAT STRING; do \
Index: fetch.c
===================================================================
RCS file: /home/cvs/src/lib/libfetch/fetch.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/fetch.c -L lib/libfetch/fetch.c -u -r1.1.1.1 -r1.2
--- lib/libfetch/fetch.c
+++ lib/libfetch/fetch.c
@@ -24,10 +24,12 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libfetch/fetch.c,v 1.41 2007/12/19 00:26:36 des Exp $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libfetch/fetch.c,v 1.38 2004/09/21 18:35:20 des Exp $");
+__MBSDID("$MidnightBSD$");
#include <sys/param.h>
#include <sys/errno.h>
@@ -56,7 +58,7 @@
#define URL_MALFORMED 1
#define URL_BAD_SCHEME 2
#define URL_BAD_PORT 3
-static struct fetcherr _url_errlist[] = {
+static struct fetcherr url_errlist[] = {
{ URL_MALFORMED, FETCH_URL, "Malformed URL" },
{ URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" },
{ URL_BAD_PORT, FETCH_URL, "Invalid server port" },
@@ -89,7 +91,7 @@
return (fetchXGetHTTP(URL, us, flags));
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
return (fetchXGetHTTP(URL, us, flags));
- _url_seterr(URL_BAD_SCHEME);
+ url_seterr(URL_BAD_SCHEME);
return (NULL);
}
@@ -121,7 +123,7 @@
return (fetchPutHTTP(URL, flags));
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
return (fetchPutHTTP(URL, flags));
- _url_seterr(URL_BAD_SCHEME);
+ url_seterr(URL_BAD_SCHEME);
return (NULL);
}
@@ -147,7 +149,7 @@
return (fetchStatHTTP(URL, us, flags));
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
return (fetchStatHTTP(URL, us, flags));
- _url_seterr(URL_BAD_SCHEME);
+ url_seterr(URL_BAD_SCHEME);
return (-1);
}
@@ -169,7 +171,7 @@
return (fetchListHTTP(URL, flags));
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
return (fetchListHTTP(URL, flags));
- _url_seterr(URL_BAD_SCHEME);
+ url_seterr(URL_BAD_SCHEME);
return (NULL);
}
@@ -264,23 +266,23 @@
struct url *u;
if (!scheme || (!host && !doc)) {
- _url_seterr(URL_MALFORMED);
+ url_seterr(URL_MALFORMED);
return (NULL);
}
if (port < 0 || port > 65535) {
- _url_seterr(URL_BAD_PORT);
+ url_seterr(URL_BAD_PORT);
return (NULL);
}
/* allocate struct url */
if ((u = calloc(1, sizeof(*u))) == NULL) {
- _fetch_syserr();
+ fetch_syserr();
return (NULL);
}
if ((u->doc = strdup(doc ? doc : "/")) == NULL) {
- _fetch_syserr();
+ fetch_syserr();
free(u);
return (NULL);
}
@@ -311,7 +313,7 @@
/* allocate struct url */
if ((u = calloc(1, sizeof(*u))) == NULL) {
- _fetch_syserr();
+ fetch_syserr();
return (NULL);
}
@@ -369,11 +371,11 @@
/* port */
if (*p == ':') {
for (q = ++p; *q && (*q != '/'); q++)
- if (isdigit(*q))
+ if (isdigit((unsigned char)*q))
u->port = u->port * 10 + (*q - '0');
else {
/* invalid port */
- _url_seterr(URL_BAD_PORT);
+ url_seterr(URL_BAD_PORT);
goto ouch;
}
p = q;
@@ -390,12 +392,12 @@
/* percent-escape whitespace. */
if ((doc = malloc(strlen(p) * 3 + 1)) == NULL) {
- _fetch_syserr();
+ fetch_syserr();
goto ouch;
}
u->doc = doc;
while (*p != '\0') {
- if (!isspace(*p)) {
+ if (!isspace((unsigned char)*p)) {
*doc++ = *p++;
} else {
*doc++ = '%';
@@ -406,7 +408,7 @@
}
*doc = '\0';
} else if ((u->doc = strdup(p)) == NULL) {
- _fetch_syserr();
+ fetch_syserr();
goto ouch;
}
Index: ftp.c
===================================================================
RCS file: /home/cvs/src/lib/libfetch/ftp.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/ftp.c -L lib/libfetch/ftp.c -u -r1.1.1.1 -r1.2
--- lib/libfetch/ftp.c
+++ lib/libfetch/ftp.c
@@ -24,10 +24,12 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libfetch/ftp.c,v 1.102 2008/02/08 09:48:48 des Exp $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libfetch/ftp.c,v 1.91 2004/09/21 18:35:20 des Exp $");
+__MBSDID("$MidnightBSD$");
/*
* Portions of this code were taken from or based on ftpio.c:
@@ -90,6 +92,9 @@
#define FTP_EPASSIVE_MODE 229
#define FTP_LOGGED_IN 230
#define FTP_FILE_ACTION_OK 250
+#define FTP_DIRECTORY_CREATED 257 /* multiple meanings */
+#define FTP_FILE_CREATED 257 /* multiple meanings */
+#define FTP_WORKING_DIRECTORY 257 /* multiple meanings */
#define FTP_NEED_PASSWORD 331
#define FTP_NEED_ACCOUNT 332
#define FTP_FILE_OK 350
@@ -99,11 +104,16 @@
static struct url cached_host;
static conn_t *cached_connection;
-#define isftpreply(foo) (isdigit(foo[0]) && isdigit(foo[1]) \
- && isdigit(foo[2]) \
- && (foo[3] == ' ' || foo[3] == '\0'))
-#define isftpinfo(foo) (isdigit(foo[0]) && isdigit(foo[1]) \
- && isdigit(foo[2]) && foo[3] == '-')
+#define isftpreply(foo) \
+ (isdigit((unsigned char)foo[0]) && \
+ isdigit((unsigned char)foo[1]) && \
+ isdigit((unsigned char)foo[2]) && \
+ (foo[3] == ' ' || foo[3] == '\0'))
+#define isftpinfo(foo) \
+ (isdigit((unsigned char)foo[0]) && \
+ isdigit((unsigned char)foo[1]) && \
+ isdigit((unsigned char)foo[2]) && \
+ foo[3] == '-')
/*
* Translate IPv4 mapped IPv6 address to IPv4 address
@@ -132,27 +142,28 @@
* Get server response
*/
static int
-_ftp_chkerr(conn_t *conn)
+ftp_chkerr(conn_t *conn)
{
- if (_fetch_getln(conn) == -1) {
- _fetch_syserr();
+ if (fetch_getln(conn) == -1) {
+ fetch_syserr();
return (-1);
}
if (isftpinfo(conn->buf)) {
while (conn->buflen && !isftpreply(conn->buf)) {
- if (_fetch_getln(conn) == -1) {
- _fetch_syserr();
+ if (fetch_getln(conn) == -1) {
+ fetch_syserr();
return (-1);
}
}
}
- while (conn->buflen && isspace(conn->buf[conn->buflen - 1]))
+ while (conn->buflen &&
+ isspace((unsigned char)conn->buf[conn->buflen - 1]))
conn->buflen--;
conn->buf[conn->buflen] = '\0';
if (!isftpreply(conn->buf)) {
- _ftp_seterr(FTP_PROTOCOL_ERROR);
+ ftp_seterr(FTP_PROTOCOL_ERROR);
return (-1);
}
@@ -167,7 +178,7 @@
* Send a command and check reply
*/
static int
-_ftp_cmd(conn_t *conn, const char *fmt, ...)
+ftp_cmd(conn_t *conn, const char *fmt, ...)
{
va_list ap;
size_t len;
@@ -180,33 +191,77 @@
if (msg == NULL) {
errno = ENOMEM;
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
- r = _fetch_putln(conn, msg, len);
+ r = fetch_putln(conn, msg, len);
free(msg);
if (r == -1) {
- _fetch_syserr();
+ fetch_syserr();
return (-1);
}
- return (_ftp_chkerr(conn));
+ return (ftp_chkerr(conn));
}
/*
* Return a pointer to the filename part of a path
*/
static const char *
-_ftp_filename(const char *file)
+ftp_filename(const char *file, int *len, int *type)
{
- char *s;
+ const char *s;
if ((s = strrchr(file, '/')) == NULL)
- return (file);
+ s = file;
else
- return (s + 1);
+ s = s + 1;
+ *len = strlen(s);
+ if (*len > 7 && strncmp(s + *len - 7, ";type=", 6) == 0) {
+ *type = s[*len - 1];
+ *len -= 7;
+ } else {
+ *type = '\0';
+ }
+ return (s);
+}
+
+/*
+ * Get current working directory from the reply to a CWD, PWD or CDUP
+ * command.
+ */
+static int
+ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen)
+{
+ char *src, *dst, *end;
+ int q;
+
+ if (conn->err != FTP_WORKING_DIRECTORY &&
+ conn->err != FTP_FILE_ACTION_OK)
+ return (FTP_PROTOCOL_ERROR);
+ end = conn->buf + conn->buflen;
+ src = conn->buf + 4;
+ if (src >= end || *src++ != '"')
+ return (FTP_PROTOCOL_ERROR);
+ for (q = 0, dst = pwd; src < end && pwdlen--; ++src) {
+ if (!q && *src == '"')
+ q = 1;
+ else if (q && *src != '"')
+ break;
+ else if (q)
+ *dst++ = '"', q = 0;
+ else
+ *dst++ = *src;
+ }
+ if (!pwdlen)
+ return (FTP_PROTOCOL_ERROR);
+ *dst = '\0';
+#if 0
+ DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd));
+#endif
+ return (FTP_OK);
}
/*
@@ -214,31 +269,140 @@
* file.
*/
static int
-_ftp_cwd(conn_t *conn, const char *file)
+ftp_cwd(conn_t *conn, const char *file)
{
- char *s;
- int e;
+ const char *beg, *end;
+ char pwd[PATH_MAX];
+ int e, i, len;
- if ((s = strrchr(file, '/')) == NULL || s == file) {
- e = _ftp_cmd(conn, "CWD /");
- } else {
- e = _ftp_cmd(conn, "CWD %.*s", s - file, file);
- }
- if (e != FTP_FILE_ACTION_OK) {
- _ftp_seterr(e);
+ /* If no slashes in name, no need to change dirs. */
+ if ((end = strrchr(file, '/')) == NULL)
+ return (0);
+ if ((e = ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY ||
+ (e = ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) {
+ ftp_seterr(e);
return (-1);
}
+ for (;;) {
+ len = strlen(pwd);
+
+ /* Look for a common prefix between PWD and dir to fetch. */
+ for (i = 0; i <= len && i <= end - file; ++i)
+ if (pwd[i] != file[i])
+ break;
+#if 0
+ DEBUG(fprintf(stderr, "have: [%.*s|%s]\n", i, pwd, pwd + i));
+ DEBUG(fprintf(stderr, "want: [%.*s|%s]\n", i, file, file + i));
+#endif
+ /* Keep going up a dir until we have a matching prefix. */
+ if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/'))
+ break;
+ if ((e = ftp_cmd(conn, "CDUP")) != FTP_FILE_ACTION_OK ||
+ (e = ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY ||
+ (e = ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) {
+ ftp_seterr(e);
+ return (-1);
+ }
+ }
+
+#ifdef FTP_COMBINE_CWDS
+ /* Skip leading slashes, even "////". */
+ for (beg = file + i; beg < end && *beg == '/'; ++beg, ++i)
+ /* nothing */ ;
+
+ /* If there is no trailing dir, we're already there. */
+ if (beg >= end)
+ return (0);
+
+ /* Change to the directory all in one chunk (e.g., foo/bar/baz). */
+ e = ftp_cmd(conn, "CWD %.*s", (int)(end - beg), beg);
+ if (e == FTP_FILE_ACTION_OK)
+ return (0);
+#endif /* FTP_COMBINE_CWDS */
+
+ /* That didn't work so go back to legacy behavior (multiple CWDs). */
+ for (beg = file + i; beg < end; beg = file + i + 1) {
+ while (*beg == '/')
+ ++beg, ++i;
+ for (++i; file + i < end && file[i] != '/'; ++i)
+ /* nothing */ ;
+ e = ftp_cmd(conn, "CWD %.*s", file + i - beg, beg);
+ if (e != FTP_FILE_ACTION_OK) {
+ ftp_seterr(e);
+ return (-1);
+ }
+ }
return (0);
}
/*
+ * Set transfer mode and data type
+ */
+static int
+ftp_mode_type(conn_t *conn, int mode, int type)
+{
+ int e;
+
+ switch (mode) {
+ case 0:
+ case 's':
+ mode = 'S';
+ case 'S':
+ break;
+ default:
+ return (FTP_PROTOCOL_ERROR);
+ }
+ if ((e = ftp_cmd(conn, "MODE %c", mode)) != FTP_OK) {
+ if (mode == 'S') {
+ /*
+ * Stream mode is supposed to be the default - so
+ * much so that some servers not only do not
+ * support any other mode, but do not support the
+ * MODE command at all.
+ *
+ * If "MODE S" fails, it is unlikely that we
+ * previously succeeded in setting a different
+ * mode. Therefore, we simply hope that the
+ * server is already in the correct mode, and
+ * silently ignore the failure.
+ */
+ } else {
+ return (e);
+ }
+ }
+
+ switch (type) {
+ case 0:
+ case 'i':
+ type = 'I';
+ case 'I':
+ break;
+ case 'a':
+ type = 'A';
+ case 'A':
+ break;
+ case 'd':
+ type = 'D';
+ case 'D':
+ /* can't handle yet */
+ default:
+ return (FTP_PROTOCOL_ERROR);
+ }
+ if ((e = ftp_cmd(conn, "TYPE %c", type)) != FTP_OK)
+ return (e);
+
+ return (FTP_OK);
+}
+
+/*
* Request and parse file stats
*/
static int
-_ftp_stat(conn_t *conn, const char *file, struct url_stat *us)
+ftp_stat(conn_t *conn, const char *file, struct url_stat *us)
{
char *ln;
- const char *s;
+ const char *filename;
+ int filenamelen, type;
struct tm tm;
time_t t;
int e;
@@ -246,21 +410,24 @@
us->size = -1;
us->atime = us->mtime = 0;
- if ((s = strrchr(file, '/')) == NULL)
- s = file;
- else
- ++s;
+ filename = ftp_filename(file, &filenamelen, &type);
+
+ if ((e = ftp_mode_type(conn, 0, type)) != FTP_OK) {
+ ftp_seterr(e);
+ return (-1);
+ }
- if ((e = _ftp_cmd(conn, "SIZE %s", s)) != FTP_FILE_STATUS) {
- _ftp_seterr(e);
+ e = ftp_cmd(conn, "SIZE %.*s", filenamelen, filename);
+ if (e != FTP_FILE_STATUS) {
+ ftp_seterr(e);
return (-1);
}
- for (ln = conn->buf + 4; *ln && isspace(*ln); ln++)
+ for (ln = conn->buf + 4; *ln && isspace((unsigned char)*ln); ln++)
/* nothing */ ;
- for (us->size = 0; *ln && isdigit(*ln); ln++)
+ for (us->size = 0; *ln && isdigit((unsigned char)*ln); ln++)
us->size = us->size * 10 + *ln - '0';
- if (*ln && !isspace(*ln)) {
- _ftp_seterr(FTP_PROTOCOL_ERROR);
+ if (*ln && !isspace((unsigned char)*ln)) {
+ ftp_seterr(FTP_PROTOCOL_ERROR);
us->size = -1;
return (-1);
}
@@ -268,11 +435,12 @@
us->size = -1;
DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size));
- if ((e = _ftp_cmd(conn, "MDTM %s", s)) != FTP_FILE_STATUS) {
- _ftp_seterr(e);
+ e = ftp_cmd(conn, "MDTM %.*s", filenamelen, filename);
+ if (e != FTP_FILE_STATUS) {
+ ftp_seterr(e);
return (-1);
}
- for (ln = conn->buf + 4; *ln && isspace(*ln); ln++)
+ for (ln = conn->buf + 4; *ln && isspace((unsigned char)*ln); ln++)
/* nothing */ ;
switch (strspn(ln, "0123456789")) {
case 14:
@@ -283,13 +451,13 @@
ln[1] = '0';
break;
default:
- _ftp_seterr(FTP_PROTOCOL_ERROR);
+ ftp_seterr(FTP_PROTOCOL_ERROR);
return (-1);
}
if (sscanf(ln, "%04d%02d%02d%02d%02d%02d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- _ftp_seterr(FTP_PROTOCOL_ERROR);
+ ftp_seterr(FTP_PROTOCOL_ERROR);
return (-1);
}
tm.tm_mon--;
@@ -318,13 +486,13 @@
int err; /* Error code */
};
-static int _ftp_readfn(void *, char *, int);
-static int _ftp_writefn(void *, const char *, int);
-static fpos_t _ftp_seekfn(void *, fpos_t, int);
-static int _ftp_closefn(void *);
+static int ftp_readfn(void *, char *, int);
+static int ftp_writefn(void *, const char *, int);
+static fpos_t ftp_seekfn(void *, fpos_t, int);
+static int ftp_closefn(void *);
static int
-_ftp_readfn(void *v, char *buf, int len)
+ftp_readfn(void *v, char *buf, int len)
{
struct ftpio *io;
int r;
@@ -344,7 +512,7 @@
}
if (io->eof)
return (0);
- r = _fetch_read(io->dconn, buf, len);
+ r = fetch_read(io->dconn, buf, len);
if (r > 0)
return (r);
if (r == 0) {
@@ -357,7 +525,7 @@
}
static int
-_ftp_writefn(void *v, const char *buf, int len)
+ftp_writefn(void *v, const char *buf, int len)
{
struct ftpio *io;
int w;
@@ -375,7 +543,7 @@
errno = io->err;
return (-1);
}
- w = _fetch_write(io->dconn, buf, len);
+ w = fetch_write(io->dconn, buf, len);
if (w >= 0)
return (w);
if (errno != EINTR)
@@ -384,7 +552,7 @@
}
static fpos_t
-_ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused)
+ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused)
{
struct ftpio *io;
@@ -398,7 +566,7 @@
}
static int
-_ftp_closefn(void *v)
+ftp_closefn(void *v)
{
struct ftpio *io;
int r;
@@ -414,20 +582,20 @@
errno = EBADF;
return (-1);
}
- _fetch_close(io->dconn);
+ fetch_close(io->dconn);
io->dir = -1;
io->dconn = NULL;
DEBUG(fprintf(stderr, "Waiting for final status\n"));
- r = _ftp_chkerr(io->cconn);
+ r = ftp_chkerr(io->cconn);
if (io->cconn == cached_connection && io->cconn->ref == 1)
cached_connection = NULL;
- _fetch_close(io->cconn);
+ fetch_close(io->cconn);
free(io);
return (r == FTP_TRANSFER_COMPLETE) ? 0 : -1;
}
static FILE *
-_ftp_setup(conn_t *cconn, conn_t *dconn, int mode)
+ftp_setup(conn_t *cconn, conn_t *dconn, int mode)
{
struct ftpio *io;
FILE *f;
@@ -440,7 +608,7 @@
io->dconn = dconn;
io->dir = mode;
io->eof = io->err = 0;
- f = funopen(io, _ftp_readfn, _ftp_writefn, _ftp_seekfn, _ftp_closefn);
+ f = funopen(io, ftp_readfn, ftp_writefn, ftp_seekfn, ftp_closefn);
if (f == NULL)
free(io);
return (f);
@@ -450,12 +618,15 @@
* Transfer file
*/
static FILE *
-_ftp_transfer(conn_t *conn, const char *oper, const char *file,
+ftp_transfer(conn_t *conn, const char *oper, const char *file,
int mode, off_t offset, const char *flags)
{
struct sockaddr_storage sa;
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin4;
+ const char *bindaddr;
+ const char *filename;
+ int filenamelen, type;
int low, pasv, verbose;
int e, sd = -1;
socklen_t l;
@@ -472,6 +643,13 @@
pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL &&
strncasecmp(s, "no", 2) != 0);
+ /* isolate filename */
+ filename = ftp_filename(file, &filenamelen, &type);
+
+ /* set transfer mode and data type */
+ if ((e = ftp_mode_type(conn, 0, type)) != FTP_OK)
+ goto ouch;
+
/* find our own address, bind, and listen */
l = sizeof(sa);
if (getsockname(conn->sd, (struct sockaddr *)&sa, &l) == -1)
@@ -481,7 +659,7 @@
/* open data socket */
if ((sd = socket(sa.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- _fetch_syserr();
+ fetch_syserr();
return (NULL);
}
@@ -493,17 +671,17 @@
/* send PASV command */
if (verbose)
- _fetch_info("setting passive mode");
+ fetch_info("setting passive mode");
switch (sa.ss_family) {
case AF_INET:
- if ((e = _ftp_cmd(conn, "PASV")) != FTP_PASSIVE_MODE)
+ if ((e = ftp_cmd(conn, "PASV")) != FTP_PASSIVE_MODE)
goto ouch;
break;
case AF_INET6:
- if ((e = _ftp_cmd(conn, "EPSV")) != FTP_EPASSIVE_MODE) {
+ if ((e = ftp_cmd(conn, "EPSV")) != FTP_EPASSIVE_MODE) {
if (e == -1)
goto ouch;
- if ((e = _ftp_cmd(conn, "LPSV")) !=
+ if ((e = ftp_cmd(conn, "LPSV")) !=
FTP_LPASSIVE_MODE)
goto ouch;
}
@@ -521,7 +699,7 @@
switch (e) {
case FTP_PASSIVE_MODE:
case FTP_LPASSIVE_MODE:
- for (p = ln + 3; *p && !isdigit(*p); p++)
+ for (p = ln + 3; *p && !isdigit((unsigned char)*p); p++)
/* nothing */ ;
if (!*p) {
e = FTP_PROTOCOL_ERROR;
@@ -555,7 +733,7 @@
/* seek to required offset */
if (offset)
- if (_ftp_cmd(conn, "REST %lu", (u_long)offset) != FTP_FILE_OK)
+ if (ftp_cmd(conn, "REST %lu", (u_long)offset) != FTP_FILE_OK)
goto sysouch;
/* construct sockaddr for data socket */
@@ -570,8 +748,8 @@
if (e == FTP_EPASSIVE_MODE)
sin6->sin6_port = htons(port);
else {
- bcopy(addr + 2, (char *)&sin6->sin6_addr, 16);
- bcopy(addr + 19, (char *)&sin6->sin6_port, 2);
+ memcpy(&sin6->sin6_addr, addr + 2, 16);
+ memcpy(&sin6->sin6_port, addr + 19, 2);
}
break;
case AF_INET:
@@ -579,8 +757,8 @@
if (e == FTP_EPASSIVE_MODE)
sin4->sin_port = htons(port);
else {
- bcopy(addr, (char *)&sin4->sin_addr, 4);
- bcopy(addr + 4, (char *)&sin4->sin_port, 2);
+ memcpy(&sin4->sin_addr, addr, 4);
+ memcpy(&sin4->sin_port, addr + 4, 2);
}
break;
default:
@@ -590,14 +768,18 @@
/* connect to data port */
if (verbose)
- _fetch_info("opening data connection");
+ fetch_info("opening data connection");
+ bindaddr = getenv("FETCH_BIND_ADDRESS");
+ if (bindaddr != NULL && *bindaddr != '\0' &&
+ fetch_bind(sd, sa.ss_family, bindaddr) != 0)
+ goto sysouch;
if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
goto sysouch;
/* make the server initiate the transfer */
if (verbose)
- _fetch_info("initiating transfer");
- e = _ftp_cmd(conn, "%s %s", oper, _ftp_filename(file));
+ fetch_info("initiating transfer");
+ e = ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename);
if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
goto ouch;
@@ -627,7 +809,7 @@
break;
}
if (verbose)
- _fetch_info("binding data socket");
+ fetch_info("binding data socket");
if (bind(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
goto sysouch;
if (listen(sd, 1) == -1)
@@ -641,7 +823,7 @@
sin4 = (struct sockaddr_in *)&sa;
a = ntohl(sin4->sin_addr.s_addr);
p = ntohs(sin4->sin_port);
- e = _ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d",
+ e = ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d",
(a >> 24) & 0xff, (a >> 16) & 0xff,
(a >> 8) & 0xff, a & 0xff,
(p >> 8) & 0xff, p & 0xff);
@@ -654,14 +836,14 @@
if (getnameinfo((struct sockaddr *)&sa, sa.ss_len,
hname, sizeof(hname),
NULL, 0, NI_NUMERICHOST) == 0) {
- e = _ftp_cmd(conn, "EPRT |%d|%s|%d|", 2, hname,
+ e = ftp_cmd(conn, "EPRT |%d|%s|%d|", 2, hname,
htons(sin6->sin6_port));
if (e == -1)
goto ouch;
}
if (e != FTP_OK) {
ap = (char *)&sin6->sin6_addr;
- e = _ftp_cmd(conn,
+ e = ftp_cmd(conn,
"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
6, 16,
UC(ap[0]), UC(ap[1]), UC(ap[2]), UC(ap[3]),
@@ -682,13 +864,13 @@
/* seek to required offset */
if (offset)
- if (_ftp_cmd(conn, "REST %ju", (uintmax_t)offset) != FTP_FILE_OK)
+ if (ftp_cmd(conn, "REST %ju", (uintmax_t)offset) != FTP_FILE_OK)
goto sysouch;
/* make the server initiate the transfer */
if (verbose)
- _fetch_info("initiating transfer");
- e = _ftp_cmd(conn, "%s %s", oper, _ftp_filename(file));
+ fetch_info("initiating transfer");
+ e = ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename);
if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
goto ouch;
@@ -699,19 +881,19 @@
sd = d;
}
- if ((df = _ftp_setup(conn, _fetch_reopen(sd), mode)) == NULL)
+ if ((df = ftp_setup(conn, fetch_reopen(sd), mode)) == NULL)
goto sysouch;
return (df);
sysouch:
- _fetch_syserr();
+ fetch_syserr();
if (sd >= 0)
close(sd);
return (NULL);
ouch:
if (e != -1)
- _ftp_seterr(e);
+ ftp_seterr(e);
if (sd >= 0)
close(sd);
return (NULL);
@@ -721,7 +903,7 @@
* Authenticate
*/
static int
-_ftp_authenticate(conn_t *conn, struct url *url, struct url *purl)
+ftp_authenticate(conn_t *conn, struct url *url, struct url *purl)
{
const char *user, *pwd, *logname;
char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1];
@@ -731,18 +913,18 @@
/* send user name and password */
if (url->user[0] == '\0')
- _fetch_netrc_auth(url);
+ fetch_netrc_auth(url);
user = url->user;
if (*user == '\0')
user = getenv("FTP_LOGIN");
if (user == NULL || *user == '\0')
user = FTP_ANONYMOUS_USER;
- if (purl && url->port == _fetch_default_port(url->scheme))
- e = _ftp_cmd(conn, "USER %s@%s", user, url->host);
+ if (purl && url->port == fetch_default_port(url->scheme))
+ e = ftp_cmd(conn, "USER %s@%s", user, url->host);
else if (purl)
- e = _ftp_cmd(conn, "USER %s@%s@%d", user, url->host, url->port);
+ e = ftp_cmd(conn, "USER %s@%s@%d", user, url->host, url->port);
else
- e = _ftp_cmd(conn, "USER %s", user);
+ e = ftp_cmd(conn, "USER %s", user);
/* did the server request a password? */
if (e == FTP_NEED_PASSWORD) {
@@ -759,7 +941,7 @@
gethostname(pbuf + len, sizeof(pbuf) - len);
pwd = pbuf;
}
- e = _ftp_cmd(conn, "PASS %s", pwd);
+ e = ftp_cmd(conn, "PASS %s", pwd);
}
return (e);
@@ -769,7 +951,7 @@
* Log on to FTP server
*/
static conn_t *
-_ftp_connect(struct url *url, struct url *purl, const char *flags)
+ftp_connect(struct url *url, struct url *purl, const char *flags)
{
conn_t *conn;
int e, direct, verbose;
@@ -792,41 +974,35 @@
/* check for proxy */
if (purl) {
/* XXX proxy authentication! */
- conn = _fetch_connect(purl->host, purl->port, af, verbose);
+ conn = fetch_connect(purl->host, purl->port, af, verbose);
} else {
/* no proxy, go straight to target */
- conn = _fetch_connect(url->host, url->port, af, verbose);
+ conn = fetch_connect(url->host, url->port, af, verbose);
purl = NULL;
}
/* check connection */
if (conn == NULL)
- /* _fetch_connect() has already set an error code */
+ /* fetch_connect() has already set an error code */
return (NULL);
/* expect welcome message */
- if ((e = _ftp_chkerr(conn)) != FTP_SERVICE_READY)
+ if ((e = ftp_chkerr(conn)) != FTP_SERVICE_READY)
goto fouch;
/* authenticate */
- if ((e = _ftp_authenticate(conn, url, purl)) != FTP_LOGGED_IN)
+ if ((e = ftp_authenticate(conn, url, purl)) != FTP_LOGGED_IN)
goto fouch;
- /* might as well select mode and type at once */
-#ifdef FTP_FORCE_STREAM_MODE
- if ((e = _ftp_cmd(conn, "MODE S")) != FTP_OK) /* default is S */
- goto fouch;
-#endif
- if ((e = _ftp_cmd(conn, "TYPE I")) != FTP_OK) /* default is A */
- goto fouch;
+ /* TODO: Request extended features supported, if any (RFC 3659). */
/* done */
return (conn);
fouch:
if (e != -1)
- _ftp_seterr(e);
- _fetch_close(conn);
+ ftp_seterr(e);
+ fetch_close(conn);
return (NULL);
}
@@ -834,19 +1010,19 @@
* Disconnect from server
*/
static void
-_ftp_disconnect(conn_t *conn)
+ftp_disconnect(conn_t *conn)
{
- (void)_ftp_cmd(conn, "QUIT");
+ (void)ftp_cmd(conn, "QUIT");
if (conn == cached_connection && conn->ref == 1)
cached_connection = NULL;
- _fetch_close(conn);
+ fetch_close(conn);
}
/*
* Check if we're already connected
*/
static int
-_ftp_isconnected(struct url *url)
+ftp_isconnected(struct url *url)
{
return (cached_connection
&& (strcmp(url->host, cached_host.host) == 0)
@@ -859,28 +1035,28 @@
* Check the cache, reconnect if no luck
*/
static conn_t *
-_ftp_cached_connect(struct url *url, struct url *purl, const char *flags)
+ftp_cached_connect(struct url *url, struct url *purl, const char *flags)
{
conn_t *conn;
int e;
/* set default port */
if (!url->port)
- url->port = _fetch_default_port(url->scheme);
+ url->port = fetch_default_port(url->scheme);
/* try to use previously cached connection */
- if (_ftp_isconnected(url)) {
- e = _ftp_cmd(cached_connection, "NOOP");
+ if (ftp_isconnected(url)) {
+ e = ftp_cmd(cached_connection, "NOOP");
if (e == FTP_OK || e == FTP_SYNTAX_ERROR)
- return (_fetch_ref(cached_connection));
+ return (fetch_ref(cached_connection));
}
/* connect to server */
- if ((conn = _ftp_connect(url, purl, flags)) == NULL)
+ if ((conn = ftp_connect(url, purl, flags)) == NULL)
return (NULL);
if (cached_connection)
- _ftp_disconnect(cached_connection);
- cached_connection = _fetch_ref(conn);
+ ftp_disconnect(cached_connection);
+ cached_connection = fetch_ref(conn);
memcpy(&cached_host, url, sizeof(*url));
return (conn);
}
@@ -889,13 +1065,15 @@
* Check the proxy settings
*/
static struct url *
-_ftp_get_proxy(const char *flags)
+ftp_get_proxy(struct url * url, const char *flags)
{
struct url *purl;
char *p;
if (flags != NULL && strchr(flags, 'd') != NULL)
return (NULL);
+ if (fetch_no_proxy_match(url->host))
+ return (NULL);
if (((p = getenv("FTP_PROXY")) || (p = getenv("ftp_proxy")) ||
(p = getenv("HTTP_PROXY")) || (p = getenv("http_proxy"))) &&
*p && (purl = fetchParseURL(p)) != NULL) {
@@ -906,7 +1084,7 @@
strcpy(purl->scheme, SCHEME_HTTP);
}
if (!purl->port)
- purl->port = _fetch_default_proxy_port(purl->scheme);
+ purl->port = fetch_default_proxy_port(purl->scheme);
if (strcasecmp(purl->scheme, SCHEME_FTP) == 0 ||
strcasecmp(purl->scheme, SCHEME_HTTP) == 0)
return (purl);
@@ -919,7 +1097,7 @@
* Process an FTP request
*/
FILE *
-_ftp_request(struct url *url, const char *op, struct url_stat *us,
+ftp_request(struct url *url, const char *op, struct url_stat *us,
struct url *purl, const char *flags)
{
conn_t *conn;
@@ -928,9 +1106,9 @@
/* check if we should use HTTP instead */
if (purl && strcasecmp(purl->scheme, SCHEME_HTTP) == 0) {
if (strcmp(op, "STAT") == 0)
- return (_http_request(url, "HEAD", us, purl, flags));
+ return (http_request(url, "HEAD", us, purl, flags));
else if (strcmp(op, "RETR") == 0)
- return (_http_request(url, "GET", us, purl, flags));
+ return (http_request(url, "GET", us, purl, flags));
/*
* Our HTTP code doesn't support PUT requests yet, so try
* a direct connection.
@@ -938,18 +1116,18 @@
}
/* connect to server */
- conn = _ftp_cached_connect(url, purl, flags);
+ conn = ftp_cached_connect(url, purl, flags);
if (purl)
fetchFreeURL(purl);
if (conn == NULL)
return (NULL);
/* change directory */
- if (_ftp_cwd(conn, url->doc) == -1)
+ if (ftp_cwd(conn, url->doc) == -1)
return (NULL);
/* stat file */
- if (us && _ftp_stat(conn, url->doc, us) == -1
+ if (us && ftp_stat(conn, url->doc, us) == -1
&& fetchLastErrCode != FETCH_PROTO
&& fetchLastErrCode != FETCH_UNAVAIL)
return (NULL);
@@ -963,7 +1141,7 @@
oflag = O_RDONLY;
/* initiate the transfer */
- return (_ftp_transfer(conn, op, url->doc, oflag, url->offset, flags));
+ return (ftp_transfer(conn, op, url->doc, oflag, url->offset, flags));
}
/*
@@ -972,7 +1150,7 @@
FILE *
fetchXGetFTP(struct url *url, struct url_stat *us, const char *flags)
{
- return (_ftp_request(url, "RETR", us, _ftp_get_proxy(flags), flags));
+ return (ftp_request(url, "RETR", us, ftp_get_proxy(url, flags), flags));
}
/*
@@ -990,9 +1168,8 @@
FILE *
fetchPutFTP(struct url *url, const char *flags)
{
-
- return (_ftp_request(url, CHECK_FLAG('a') ? "APPE" : "STOR", NULL,
- _ftp_get_proxy(flags), flags));
+ return (ftp_request(url, CHECK_FLAG('a') ? "APPE" : "STOR", NULL,
+ ftp_get_proxy(url, flags), flags));
}
/*
@@ -1003,9 +1180,14 @@
{
FILE *f;
- f = _ftp_request(url, "STAT", us, _ftp_get_proxy(flags), flags);
+ f = ftp_request(url, "STAT", us, ftp_get_proxy(url, flags), flags);
if (f == NULL)
return (-1);
+ /*
+ * When op is "STAT", ftp_request() will return either NULL or
+ * (FILE *)1, never a valid FILE *, so we mustn't fclose(f) before
+ * returning, as it would cause a segfault.
+ */
return (0);
}
Index: fetch.h
===================================================================
RCS file: /home/cvs/src/lib/libfetch/fetch.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L lib/libfetch/fetch.h -L lib/libfetch/fetch.h -u -r1.1.1.1 -r1.2
--- lib/libfetch/fetch.h
+++ lib/libfetch/fetch.h
@@ -25,6 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
+ * $MidnightBSD$
* $FreeBSD: src/lib/libfetch/fetch.h,v 1.26 2004/09/21 18:35:20 des Exp $
*/
More information about the Midnightbsd-cvs
mailing list