summaryrefslogtreecommitdiffstats
path: root/lib/libfetch
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>1998-07-12 22:34:40 +0000
committerdes <des@FreeBSD.org>1998-07-12 22:34:40 +0000
commit54143a63f80a2475a26b79155d70cd29d4852b61 (patch)
tree1f893e49f8094a6d683a2997270fc22c324aec85 /lib/libfetch
parent2480a048bed9522e1b2d9121e44db4c7398791b9 (diff)
downloadFreeBSD-src-54143a63f80a2475a26b79155d70cd29d4852b61.zip
FreeBSD-src-54143a63f80a2475a26b79155d70cd29d4852b61.tar.gz
Base64 code (and the MIT copyright) moved to http.c
FTP STORe and APPEnd added. FTP proxy support added (untested).
Diffstat (limited to 'lib/libfetch')
-rw-r--r--lib/libfetch/base64.c90
-rw-r--r--lib/libfetch/ftp.c139
-rw-r--r--lib/libfetch/http.c174
3 files changed, 223 insertions, 180 deletions
diff --git a/lib/libfetch/base64.c b/lib/libfetch/base64.c
deleted file mode 100644
index fcb628c..0000000
--- a/lib/libfetch/base64.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*-
- * Copyright 1997 Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby
- * granted, provided that both the above copyright notice and this
- * permission notice appear in all copies, that both the above
- * copyright notice and this permission notice appear in all
- * supporting documentation, and that the name of M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. M.I.T. makes
- * no representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied
- * warranty.
- *
- * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
- * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
- * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY 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.
- *
- * $Id: util.c,v 1.6 1998/02/20 05:08:53 jb Exp $
- */
-
-#include <stdio.h>
-
-/*
- * Not much left of the original MIT code, but it's still derived from it
- * so I'll keep their copyright. This is taken from util.c in MIT fetch.
- *
- * -- DES 1998/05/22
- */
-
-/*
- * Implement the `base64' encoding as described in RFC 1521.
- */
-static const char base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-int
-fprint64(FILE *f, const unsigned char *buf)
-{
- int len = 0, l = 0;
- unsigned int tmp;
-
- while (buf[len])
- len++;
-
- while (len >= 3) {
- tmp = buf[0] << 16 | buf[1] << 8 | buf[2];
- fprintf(f, "%c%c%c%c",
- base64[(tmp >> 18) & 077],
- base64[(tmp >> 12) & 077],
- base64[(tmp >> 6) & 077],
- base64[tmp & 077]);
- len -= 3;
- buf += 3;
- l += 4;
- }
-
- /* RFC 1521 enumerates these three possibilities... */
- switch(len) {
- case 2:
- tmp = buf[0] << 16 | buf[1] << 8;
- fprintf(f, "%c%c%c=",
- base64[(tmp >> 18) & 077],
- base64[(tmp >> 12) & 077],
- base64[(tmp >> 6) & 077]);
- l += 4;
- break;
- case 1:
- tmp = buf[0] << 16;
- fprintf(f, "%c%c==",
- base64[(tmp >> 18) & 077],
- base64[(tmp >> 12) & 077]);
- l += 4;
- break;
- case 0:
- break;
- }
-
- return l;
-}
diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c
index 9f93297..b38a4e7 100644
--- a/lib/libfetch/ftp.c
+++ b/lib/libfetch/ftp.c
@@ -25,7 +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.
*
- * $Id: ftp.c,v 1.1.1.1 1998/07/09 16:52:42 des Exp $
+ * $Id: ftp.c,v 1.3 1998/07/11 21:29:08 des Exp $
*/
/*
@@ -190,10 +190,10 @@ _ftp_cmd(FILE *f, char *fmt, ...)
}
/*
- * Retrieve file
+ * Transfer file
*/
static FILE *
-_ftp_retrieve(FILE *cf, char *file, int pasv)
+_ftp_transfer(FILE *cf, char *oper, char *file, char *mode, int pasv)
{
struct sockaddr_in sin;
int sd = -1, l;
@@ -252,7 +252,7 @@ _ftp_retrieve(FILE *cf, char *file, int pasv)
goto sysouch;
/* make the server initiate the transfer */
- if (_ftp_cmd(cf, "RETR %s" ENDL, s) != FTP_OPEN_DATA_CONNECTION)
+ if (_ftp_cmd(cf, "%s %s" ENDL, oper, s) != FTP_OPEN_DATA_CONNECTION)
goto ouch;
} else {
@@ -281,7 +281,7 @@ _ftp_retrieve(FILE *cf, char *file, int pasv)
goto ouch;
/* make the server initiate the transfer */
- if (_ftp_cmd(cf, "RETR %s" ENDL, s) != FTP_OPEN_DATA_CONNECTION)
+ if (_ftp_cmd(cf, "%s %s" ENDL, oper, s) != FTP_OPEN_DATA_CONNECTION)
goto ouch;
/* accept the incoming connection and go to town */
@@ -291,7 +291,7 @@ _ftp_retrieve(FILE *cf, char *file, int pasv)
sd = d;
}
- if ((df = fdopen(sd, "r")) == NULL)
+ if ((df = fdopen(sd, mode)) == NULL)
goto sysouch;
return df;
@@ -303,33 +303,38 @@ ouch:
}
/*
- * Store file
- */
-static FILE *
-_ftp_store(FILE *cf, char *file, int pasv)
-{
- fprintf(stderr, "_ftp_store: not implemented yet.\n");
-
- cf = cf;
- file = file;
- pasv = pasv;
- return NULL;
-}
-
-/*
* Log on to FTP server
*/
static FILE *
_ftp_connect(char *host, int port, char *user, char *pwd)
{
- int sd, e;
+ int sd, e, pp = FTP_DEFAULT_PORT;
+ char *p, *q;
FILE *f;
- /* establish control connection */
- if ((sd = fetchConnect(host, port)) < 0) {
+ /* check for proxy */
+ if ((p = getenv("FTP_PROXY")) != NULL) {
+ if ((q = strchr(p, ':')) != NULL) {
+ /* XXX check that it's a valid number */
+ pp = atoi(q+1);
+ }
+ if (q)
+ *q = 0;
+ sd = fetchConnect(p, pp);
+ if (q)
+ *q = ':';
+ } else {
+ /* no proxy, go straight to target */
+ sd = fetchConnect(host, port);
+ }
+
+ /* check connection */
+ if (sd < 0) {
_ftp_syserr();
return NULL;
}
+
+ /* streams make life easier */
if ((f = fdopen(sd, "r+")) == NULL) {
_ftp_syserr();
goto ouch;
@@ -340,20 +345,32 @@ _ftp_connect(char *host, int port, char *user, char *pwd)
goto fouch;
/* send user name and password */
- e = _ftp_cmd(f, "USER %s" ENDL, user);
- if (e == FTP_NEED_PASSWORD) /* server requested a password */
+ if (!user || !*user)
+ user = FTP_ANONYMOUS_USER;
+ e = p ? _ftp_cmd(f, "USER %s@%s@%d" ENDL, user, host, port)
+ : _ftp_cmd(f, "USER %s" ENDL, user);
+
+ /* did the server request a password? */
+ if (e == FTP_NEED_PASSWORD) {
+ if (!pwd || !*pwd)
+ pwd = FTP_ANONYMOUS_PASSWORD;
e = _ftp_cmd(f, "PASS %s" ENDL, pwd);
- if (e == FTP_NEED_ACCOUNT) /* server requested an account */
+ }
+
+ /* did the server request an account? */
+ if (e == FTP_NEED_ACCOUNT)
/* help! */ ;
- if (e != FTP_LOGGED_IN) /* won't let us near the WaReZ */
+
+ /* we should be done by now */
+ if (e != FTP_LOGGED_IN)
goto fouch;
/* might as well select mode and type at once */
#ifdef FTP_FORCE_STREAM_MODE
- if (_ftp_cmd(f, "MODE S" ENDL) != FTP_OK)
+ if (_ftp_cmd(f, "MODE S" ENDL) != FTP_OK) /* default is S */
goto ouch;
#endif
- if (_ftp_cmd(f, "TYPE I" ENDL) != FTP_OK)
+ if (_ftp_cmd(f, "TYPE I" ENDL) != FTP_OK) /* default is A */
goto ouch;
/* done */
@@ -390,19 +407,15 @@ _ftp_isconnected(url_t *url)
&& (url->port == cached_host.port));
}
-FILE *
-fetchGetFTP(url_t *url, char *flags)
+/*
+ * FTP session
+ */
+static FILE *
+fetchXxxFTP(url_t *url, char *oper, char *mode, char *flags)
{
FILE *cf = NULL;
int e;
-#ifdef DEFAULT_TO_ANONYMOUS
- if (!url->user[0]) {
- strcpy(url->user, FTP_ANONYMOUS_USER);
- strcpy(url->pwd, FTP_ANONYMOUS_PASSWORD);
- }
-#endif
-
/* set default port */
if (!url->port)
url->port = FTP_DEFAULT_PORT;
@@ -427,50 +440,22 @@ fetchGetFTP(url_t *url, char *flags)
}
/* initiate the transfer */
- return _ftp_retrieve(cf, url->doc, (flags && strchr(flags, 'p')));
+ return _ftp_transfer(cf, oper, url->doc, mode, (flags && strchr(flags, 'p')));
}
/*
- * Upload a file.
- * Hmmm, that's almost an exact duplicate of the above...
+ * Itsy bitsy teeny weenie
*/
FILE *
-fetchPutFTP(url_t *url, char *flags)
+fetchGetFTP(url_t *url, char *flags)
{
- FILE *cf = NULL;
- int e;
-
-#ifdef DEFAULT_TO_ANONYMOUS
- if (!url->user[0]) {
- strcpy(url->user, FTP_ANONYMOUS_USER);
- strcpy(url->pwd, FTP_ANONYMOUS_PASSWORD);
- }
-#endif
-
- /* set default port */
- if (!url->port)
- url->port = htons(FTP_DEFAULT_PORT);
-
- /* try to use previously cached connection */
- if (_ftp_isconnected(url)) {
- fprintf(cached_socket, "PWD" ENDL);
- _ftp_chkerr(cached_socket, &e);
- if (e > 0)
- cf = cached_socket;
- }
-
- /* connect to server */
- if (!cf) {
- cf = _ftp_connect(url->host, url->port, url->user, url->pwd);
- if (!cf)
- return NULL;
- if (cached_socket)
- _ftp_disconnect(cached_socket);
- cached_socket = cf;
- memcpy(&cached_host, url, sizeof(url_t));
- }
-
+ return fetchXxxFTP(url, "RETR", "r", flags);
+}
- /* initiate the transfer */
- return _ftp_store(cf, url->doc, (flags && strchr(flags, 'p')));
+FILE *
+fetchPutFTP(url_t *url, char *flags)
+{
+ if (flags && strchr(flags, 'a'))
+ return fetchXxxFTP(url, "APPE", "w", flags);
+ else return fetchXxxFTP(url, "STOR", "w", flags);
}
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index 3178e2a..68b3525 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -25,9 +25,41 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: http.c,v 1.1.1.1 1998/07/09 16:52:41 des Exp $
+ * $Id: http.c,v 1.3 1998/07/11 21:29:08 des Exp $
*/
+/*
+ * The base64 code in this file is based on code from MIT fetch, which
+ * has the following copyright and license:
+ *
+ *-
+ * Copyright 1997 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY 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. */
+
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/socket.h>
@@ -38,6 +70,7 @@
#include <err.h>
#include <ctype.h>
#include <netdb.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -54,8 +87,6 @@
extern char *__progname;
-extern int fprint64(FILE *f, const unsigned char *buf);
-
#define ENDL "\r\n"
struct cookie
@@ -71,6 +102,9 @@ struct cookie
unsigned b_len, chunksize;
};
+/*
+ * Look up error code
+ */
static const char *
_http_errstring(int e)
{
@@ -82,6 +116,29 @@ _http_errstring(int e)
return p->string;
}
+/*
+ * Send a formatted line; optionally echo to terminal
+ */
+static int
+_http_cmd(FILE *f, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(f, fmt, ap);
+#ifndef NDEBUG
+ fprintf(stderr, "\033[1m>>> ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\033[m");
+#endif
+ va_end(ap);
+
+ return 0; /* XXX */
+}
+
+/*
+ * Fill the input buffer, do chunk decoding on the fly
+ */
static char *
_http_fillbuf(struct cookie *c)
{
@@ -119,6 +176,9 @@ _http_fillbuf(struct cookie *c)
return c->buf;
}
+/*
+ * Read function
+ */
static int
_http_readfn(struct cookie *c, char *buf, int len)
{
@@ -142,6 +202,9 @@ _http_readfn(struct cookie *c, char *buf, int len)
else return pos;
}
+/*
+ * Write function
+ */
static int
_http_writefn(struct cookie *c, const char *buf, int len)
{
@@ -149,6 +212,9 @@ _http_writefn(struct cookie *c, const char *buf, int len)
return r ? r : -1;
}
+/*
+ * Close function
+ */
static int
_http_closefn(struct cookie *c)
{
@@ -157,6 +223,9 @@ _http_closefn(struct cookie *c)
return (r == EOF) ? -1 : 0;
}
+/*
+ * Extract content type from cookie
+ */
char *
fetchContentType(FILE *f)
{
@@ -167,6 +236,85 @@ fetchContentType(FILE *f)
return f->_cookie ? (((struct cookie *)f->_cookie)->content_type) : NULL;
}
+/*
+ * Base64 encoding
+ */
+int
+_http_base64(char *dst, char *src, int l)
+{
+ static const char base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ int t, r = 0;
+
+ while (l >= 3) {
+ t = (src[0] << 16) | (src[1] << 8) | src[2];
+ dst[0] = base64[(t >> 18) & 0x3f];
+ dst[1] = base64[(t >> 12) & 0x3f];
+ dst[2] = base64[(t >> 6) & 0x3f];
+ dst[3] = base64[(t >> 0) & 0x3f];
+ src += 3; l -= 3;
+ dst += 4; r += 4;
+ }
+
+ switch (l) {
+ case 2:
+ t = (src[0] << 16) | (src[1] << 8);
+ dst[0] = base64[(t >> 18) & 0x3f];
+ dst[1] = base64[(t >> 12) & 0x3f];
+ dst[2] = base64[(t >> 6) & 0x3f];
+ dst[3] = '=';
+ dst += 4;
+ r += 4;
+ break;
+ case 1:
+ t = src[0] << 16;
+ dst[0] = base64[(t >> 18) & 0x3f];
+ dst[1] = base64[(t >> 12) & 0x3f];
+ dst[2] = dst[3] = '=';
+ dst += 4;
+ r += 4;
+ break;
+ case 0:
+ break;
+ }
+
+ *dst = 0;
+ return r;
+}
+
+/*
+ * Encode username and password
+ */
+char *
+_http_auth(char *usr, char *pwd)
+{
+ int len, lu, lp;
+ char *str, *s;
+
+ lu = strlen(usr);
+ lp = strlen(pwd);
+
+ len = (lu * 4 + 2) / 3 /* user name, round up */
+ + 1 /* colon */
+ + (lp * 4 + 2) / 3 /* password, round up */
+ + 1; /* null */
+
+ if ((s = str = (char *)malloc(len)) == NULL)
+ return NULL;
+
+ s += _http_base64(s, usr, lu);
+ *s++ = ':';
+ s += _http_base64(s, pwd, lp);
+ *s = 0;
+
+ return str;
+}
+
+/*
+ * retrieve a file by HTTP
+ */
FILE *
fetchGetHTTP(url_t *URL, char *flags)
{
@@ -220,20 +368,20 @@ fetchGetHTTP(url_t *URL, char *flags)
c->real_f = f;
/* send request (proxies require absolute form, so use that) */
- fprintf(f, "GET http://%s:%d/%s HTTP/1.1" ENDL,
- URL->host, URL->port, URL->doc);
+ _http_cmd(f, "GET http://%s:%d%s HTTP/1.1" ENDL,
+ URL->host, URL->port, URL->doc);
/* start sending headers away */
if (URL->user[0] || URL->pwd[0]) {
- fprintf(f, "Authorization: Basic ");
- fprint64(f, (const unsigned char *)URL->user);
- fputc(':', f);
- fprint64(f, (const unsigned char *)URL->pwd);
- fputs(ENDL, f);
+ char *auth_str = _http_auth(URL->user, URL->pwd);
+ if (!auth_str)
+ goto fouch;
+ _http_cmd(f, "Authorization: Basic %s" ENDL, auth_str);
+ free(auth_str);
}
- fprintf(f, "Host: %s:%d" ENDL, URL->host, URL->port);
- fprintf(f, "User-Agent: %s " _LIBFETCH_VER ENDL, __progname);
- fprintf(f, "Connection: close" ENDL ENDL);
+ _http_cmd(f, "Host: %s:%d" ENDL, URL->host, URL->port);
+ _http_cmd(f, "User-Agent: %s " _LIBFETCH_VER ENDL, __progname);
+ _http_cmd(f, "Connection: close" ENDL ENDL);
/* get response */
if ((ln = fgetln(f, &len)) == NULL)
OpenPOWER on IntegriCloud