Base64 code (and the MIT copyright) moved to http.c

FTP STORe and APPEnd added.
FTP proxy support added (untested).
This commit is contained in:
Dag-Erling Smørgrav 1998-07-12 22:34:40 +00:00
parent e1b7cfe2bf
commit f62e5228fd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=37608
3 changed files with 223 additions and 180 deletions

View file

@ -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;
}

View file

@ -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;
@ -302,34 +302,39 @@ _ftp_retrieve(FILE *cf, char *file, int pasv)
return NULL;
}
/*
* 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 *
fetchGetFTP(url_t *url, char *flags)
{
return fetchXxxFTP(url, "RETR", "r", flags);
}
FILE *
fetchPutFTP(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));
}
/* initiate the transfer */
return _ftp_store(cf, url->doc, (flags && strchr(flags, 'p')));
if (flags && strchr(flags, 'a'))
return fetchXxxFTP(url, "APPE", "w", flags);
else return fetchXxxFTP(url, "STOR", "w", flags);
}

View file

@ -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)