Bozohttpd

Check-in [6d39f799f6]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Use existing content_map to provide cache control header per file type

Ideally I'd prefer to do it with a regex or partial match on the content type, but everything is already setup for us to piggyback on this instead. I.e. I'd like to do multiple arguments like this:

-h "image" "private, max-age=604800" -h "css" "private, max-age=86400"

or a single argument where we split the string on a comma:

-h "image,css" "private, max-age=604800"

but instead I am happy enough to be able to do:

-h .jpg "private, max-age=604800" -h .png "private, max-age=86400"

It's good enough for what I want to stop here.

- Adds a new cache-bozo.c file
- Adds a new field in the existing map used for the cache control header
- Extends all existing functions as required to reference this new field.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA1: 6d39f799f600f823d8d1cde2545aacd15e903a70
User & Date: atomicules 2017-12-02 22:37:55
Context
2017-12-02
22:37
Use existing content_map to provide cache control header per file type

Ideally I'd prefer to do it with a regex or partial match on the content type, but everything is already setup for us to piggyback on this instead. I.e. I'd like to do multiple arguments like this:

-h "image" "private, max-age=604800" -h "css" "private, max-age=86400"

or a single argument where we split the string on a comma:

-h "image,css" "private, max-age=604800"

but instead I am happy enough to be able to do:

-h .jpg "private, max-age=604800" -h .png "private, max-age=86400"

It's good enough for what I want to stop here.

- Adds a new cache-bozo.c file
- Adds a new field in the existing map used for the cache control header
- Extends all existing functions as required to reference this new field. Leaf check-in: 6d39f799f6 user: atomicules tags: trunk

2017-11-25
22:13
Set cache-control only for images

A bit of an intermediate commit, just investigating what works. I think really
need to be able to pass in a string and a cache-control header and it'll use
strstr to determine which header to set. I.e so you can pass in:

"image" "max-age=604800"
"css" "max-age=86400"

The bit I'm then missing is how to set a catch all or "owtelse" cache-control?
Maybe look for one argument? check-in: dda2552f49 user: atomicules tags: trunk

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#   % make COPTS="-DDO_HTPASSWD"

COPTS+=	-DDO_HTPASSWD
PROG=	bozohttpd
LINKS=	${BINDIR}/bozohttpd ${BINDIR}/httpd
MAN=	bozohttpd.8
MLINKS+=bozohttpd.8 httpd.8
SRCS=	bozohttpd.c ssl-bozo.c auth-bozo.c cgi-bozo.c daemon-bozo.c \
	tilde-luzah-bozo.c dir-index-bozo.c content-bozo.c lua-bozo.c
SRCS+=	main.c

LDADD=	-lcrypt -llua -lm
DPADD=	${LIBCRYPT} ${LIBLUA} ${LIBM}

WARNS?=	4







|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#   % make COPTS="-DDO_HTPASSWD"

COPTS+=	-DDO_HTPASSWD
PROG=	bozohttpd
LINKS=	${BINDIR}/bozohttpd ${BINDIR}/httpd
MAN=	bozohttpd.8
MLINKS+=bozohttpd.8 httpd.8
SRCS=	bozohttpd.c ssl-bozo.c auth-bozo.c cgi-bozo.c cache-bozo.c daemon-bozo.c \
	tilde-luzah-bozo.c dir-index-bozo.c content-bozo.c lua-bozo.c
SRCS+=	main.c

LDADD=	-lcrypt -llua -lm
DPADD=	${LIBCRYPT} ${LIBLUA} ${LIBM}

WARNS?=	4

Changes to bozohttpd.c.

1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
....
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
....
1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
....
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
....
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
		     scheme, hostname, portbuf, url, quest, query);

	bozowarn(httpd, "redirecting %s", finalurl);
	debug((httpd, DEBUG_FAT, "redirecting %s", finalurl));

	bozo_printf(httpd, "%s 301 Document Moved\r\n", request->hr_proto);
	if (request->hr_proto != httpd->consts.http_09)
		bozo_print_header(request, NULL, "text/html", NULL);
	if (request->hr_proto != httpd->consts.http_09)
		bozo_printf(httpd, "Location: %s\r\n", finalurl);
	bozo_printf(httpd, "\r\n");
	if (request->hr_method == HTTP_HEAD)
		goto head;
	bozo_printf(httpd, "<html><head><title>Document Moved</title></head>\n");
	bozo_printf(httpd, "<body><h1>Document Moved</h1>\n");
................................................................................
void
bozo_process_request(bozo_httpreq_t *request)
{
	bozohttpd_t *httpd = request->hr_httpd;
	struct	stat sb;
	time_t timestamp;
	char	*file;
	const char *type, *encoding;
	int	fd, isindex;

	/*
	 * note that transform_request chdir()'s if required.  also note
	 * that cgi is handed here.  if transform_request() returns 0
	 * then the request has been handled already.
	 */
................................................................................
		bozo_printf(httpd, "%s 206 Partial Content\r\n",
				request->hr_proto);
	else
		bozo_printf(httpd, "%s 200 OK\r\n", request->hr_proto);

	if (request->hr_proto != httpd->consts.http_09) {
		type = bozo_content_type(request, file);

		if (!encoding)
			encoding = bozo_content_encoding(request, file);

		bozo_print_header(request, &sb, type, encoding);
		bozo_printf(httpd, "\r\n");
	}
	bozo_flush(httpd, stdout);

	if (request->hr_method != HTTP_HEAD) {
		off_t szleft, cur_byte_pos;

................................................................................
		    "no permission to open redirect file");
	return bozo_auth_check_special_files(request, name);
}

/* generic header printing routine */
void
bozo_print_header(bozo_httpreq_t *request,
		struct stat *sbp, const char *type, const char *encoding)
{
	bozohttpd_t *httpd = request->hr_httpd;
	off_t len;
	char	date[40];
	bozoheaders_t *hdr;

	SIMPLEQ_FOREACH(hdr, &request->hr_replheaders, h_next) {
................................................................................
		struct	tm *tm;

		tm = gmtime(&sbp->st_mtime);
		strftime(filedate, sizeof filedate,
		    "%a, %d %b %Y %H:%M:%S GMT", tm);
		bozo_printf(httpd, "Last-Modified: %s\r\n", filedate);
	}
	if (httpd->cache_control_headers && (strstr(type, "image") != NULL))
		bozo_printf(httpd, "Cache-Control: %s\r\n", httpd->cache_control_headers);
	if (type && *type)
		bozo_printf(httpd, "Content-Type: %s\r\n", type);
	if (encoding && *encoding)
		bozo_printf(httpd, "Content-Encoding: %s\r\n", encoding);
	if (sbp) {
		if (request->hr_have_range) {
			len = request->hr_last_byte_pos -







|







 







|







 







>



|







 







|







 







|
|







1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
....
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
....
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
....
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
....
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
		     scheme, hostname, portbuf, url, quest, query);

	bozowarn(httpd, "redirecting %s", finalurl);
	debug((httpd, DEBUG_FAT, "redirecting %s", finalurl));

	bozo_printf(httpd, "%s 301 Document Moved\r\n", request->hr_proto);
	if (request->hr_proto != httpd->consts.http_09)
		bozo_print_header(request, NULL, "text/html", NULL, NULL);
	if (request->hr_proto != httpd->consts.http_09)
		bozo_printf(httpd, "Location: %s\r\n", finalurl);
	bozo_printf(httpd, "\r\n");
	if (request->hr_method == HTTP_HEAD)
		goto head;
	bozo_printf(httpd, "<html><head><title>Document Moved</title></head>\n");
	bozo_printf(httpd, "<body><h1>Document Moved</h1>\n");
................................................................................
void
bozo_process_request(bozo_httpreq_t *request)
{
	bozohttpd_t *httpd = request->hr_httpd;
	struct	stat sb;
	time_t timestamp;
	char	*file;
	const char *type, *encoding, *cacheheader;
	int	fd, isindex;

	/*
	 * note that transform_request chdir()'s if required.  also note
	 * that cgi is handed here.  if transform_request() returns 0
	 * then the request has been handled already.
	 */
................................................................................
		bozo_printf(httpd, "%s 206 Partial Content\r\n",
				request->hr_proto);
	else
		bozo_printf(httpd, "%s 200 OK\r\n", request->hr_proto);

	if (request->hr_proto != httpd->consts.http_09) {
		type = bozo_content_type(request, file);
		cacheheader = bozo_content_cache(request, file);
		if (!encoding)
			encoding = bozo_content_encoding(request, file);

		bozo_print_header(request, &sb, type, encoding, cacheheader);
		bozo_printf(httpd, "\r\n");
	}
	bozo_flush(httpd, stdout);

	if (request->hr_method != HTTP_HEAD) {
		off_t szleft, cur_byte_pos;

................................................................................
		    "no permission to open redirect file");
	return bozo_auth_check_special_files(request, name);
}

/* generic header printing routine */
void
bozo_print_header(bozo_httpreq_t *request,
		struct stat *sbp, const char *type, const char *encoding, const char *cacheheader)
{
	bozohttpd_t *httpd = request->hr_httpd;
	off_t len;
	char	date[40];
	bozoheaders_t *hdr;

	SIMPLEQ_FOREACH(hdr, &request->hr_replheaders, h_next) {
................................................................................
		struct	tm *tm;

		tm = gmtime(&sbp->st_mtime);
		strftime(filedate, sizeof filedate,
		    "%a, %d %b %Y %H:%M:%S GMT", tm);
		bozo_printf(httpd, "Last-Modified: %s\r\n", filedate);
	}
	if (cacheheader && *cacheheader)
		bozo_printf(httpd, "Cache-Control: %s\r\n", cacheheader);
	if (type && *type)
		bozo_printf(httpd, "Content-Type: %s\r\n", type);
	if (encoding && *encoding)
		bozo_printf(httpd, "Content-Encoding: %s\r\n", encoding);
	if (sbp) {
		if (request->hr_have_range) {
			len = request->hr_last_byte_pos -

Changes to bozohttpd.h.

74
75
76
77
78
79
80

81
82
83
84
85
86
87
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
291
292
293
294
295
296
297





298
299
300
301
302
303
304

typedef struct bozo_content_map_t {
	const char	*name;		/* postfix of file */
	const char	*type;		/* matching content-type */
	const char	*encoding;	/* matching content-encoding */
	const char	*encoding11;	/* matching content-encoding (HTTP/1.1) */
	const char	*cgihandler;	/* optional CGI handler */

} bozo_content_map_t;

/* this struct holds the bozo constants */
typedef struct bozo_consts_t {
	const char	*http_09;	/* "HTTP/0.9" */
	const char	*http_10;	/* "HTTP/1.0" */
	const char	*http_11;	/* "HTTP/1.1" */
................................................................................
#define	debug(x)
#endif /* NO_DEBUG */

int	bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *);

int	bozo_check_special_files(bozo_httpreq_t *, const char *);
char	*bozo_http_date(char *, size_t);
void	bozo_print_header(bozo_httpreq_t *, struct stat *, const char *,
			  const char *);
char	*bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute);
char	*bozo_escape_html(bozohttpd_t *httpd, const char *url);
int	bozo_decode_url_percent(bozo_httpreq_t *, char *);

/* these are similar to libc functions, no underscore here */
void	bozowarn(bozohttpd_t *, const char *, ...)
		BOZO_PRINTFLIKE(2, 3);
................................................................................
#else
void	bozo_cgi_setbin(bozohttpd_t *, const char *);
void	bozo_setenv(bozohttpd_t *, const char *, const char *, char **);
int	bozo_process_cgi(bozo_httpreq_t *);
void	bozo_add_content_map_cgi(bozohttpd_t *, const char *, const char *);
#endif /* NO_CGIBIN_SUPPORT */







/* lua-bozo.c */
#ifdef NO_LUA_SUPPORT
#define bozo_process_lua(h)				0
#else
void	bozo_add_lua_map(bozohttpd_t *, const char *, const char *);
int	bozo_process_lua(bozo_httpreq_t *);







>







 







|
<







 







>
>
>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
...
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

typedef struct bozo_content_map_t {
	const char	*name;		/* postfix of file */
	const char	*type;		/* matching content-type */
	const char	*encoding;	/* matching content-encoding */
	const char	*encoding11;	/* matching content-encoding (HTTP/1.1) */
	const char	*cgihandler;	/* optional CGI handler */
	const char	*cacheheader;	/* optional Content-Cache header */
} bozo_content_map_t;

/* this struct holds the bozo constants */
typedef struct bozo_consts_t {
	const char	*http_09;	/* "HTTP/0.9" */
	const char	*http_10;	/* "HTTP/1.0" */
	const char	*http_11;	/* "HTTP/1.1" */
................................................................................
#define	debug(x)
#endif /* NO_DEBUG */

int	bozo_http_error(bozohttpd_t *, int, bozo_httpreq_t *, const char *);

int	bozo_check_special_files(bozo_httpreq_t *, const char *);
char	*bozo_http_date(char *, size_t);
void	bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, const char *, const char *);

char	*bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute);
char	*bozo_escape_html(bozohttpd_t *httpd, const char *url);
int	bozo_decode_url_percent(bozo_httpreq_t *, char *);

/* these are similar to libc functions, no underscore here */
void	bozowarn(bozohttpd_t *, const char *, ...)
		BOZO_PRINTFLIKE(2, 3);
................................................................................
#else
void	bozo_cgi_setbin(bozohttpd_t *, const char *);
void	bozo_setenv(bozohttpd_t *, const char *, const char *, char **);
int	bozo_process_cgi(bozo_httpreq_t *);
void	bozo_add_content_map_cgi(bozohttpd_t *, const char *, const char *);
#endif /* NO_CGIBIN_SUPPORT */


/* cache-bozo.c */
void	bozo_add_content_map_cache(bozohttpd_t *, const char *, const char *);
const char *bozo_content_cache(bozo_httpreq_t *, const char *);


/* lua-bozo.c */
#ifdef NO_LUA_SUPPORT
#define bozo_process_lua(h)				0
#else
void	bozo_add_lua_map(bozohttpd_t *, const char *, const char *);
int	bozo_process_lua(bozo_httpreq_t *);

Added cache-bozo.c.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* Based on cgi-bozo.c and content-bozo.c */

/* content-cache maps are "content type string to match on" "content-cache string" */

#include <sys/param.h>

#include <errno.h>
#include <string.h>

#include "bozohttpd.h"

/*
 * given the file name, return a valid Content-Cache: header
 */
/* ARGSUSED */
const char *
bozo_content_cache(bozo_httpreq_t *request, const char *file)
{
	bozohttpd_t *httpd = request->hr_httpd;
	bozo_content_map_t	*map;

	map = bozo_match_content_map(httpd, file, 0);
	if (map)
		return map->cacheheader;
	return NULL;
}

void
bozo_add_content_map_cache(bozohttpd_t *httpd, const char *arg,
                         const char *cacheheader)
{
	bozo_content_map_t *map;

	debug((httpd, DEBUG_NORMAL, "bozo_add_content_map_cache: type %s cache %s",
		arg, cacheheader));

	map = bozo_get_content_map(httpd, arg);
	map->name = arg;
	map->type = map->encoding = map->encoding11 = map->cgihandler = NULL;
	map->cacheheader = cacheheader;
}

Changes to content-bozo.c.

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
...
293
294
295
296
297
298
299

300
301
 * this map and the functions below map between filenames and the
 * content type and content encoding definitions.  this should become
 * a configuration file, perhaps like apache's mime.types (but that
 * has less info per-entry).
 */

static bozo_content_map_t static_content_map[] = {
	{ ".html",	"text/html",			"",		"", NULL },
	{ ".htm",	"text/html",			"",		"", NULL },
	{ ".gif",	"image/gif",			"",		"", NULL },
	{ ".jpeg",	"image/jpeg",			"",		"", NULL },
	{ ".jpg",	"image/jpeg",			"",		"", NULL },
	{ ".jpe",	"image/jpeg",			"",		"", NULL },
	{ ".png",	"image/png",			"",		"", NULL },
	{ ".mp3",	"audio/mpeg",			"",		"", NULL },
	{ ".css",	"text/css",			"",		"", NULL },
	{ ".txt",	"text/plain",			"",		"", NULL },
	{ ".swf",	"application/x-shockwave-flash","",		"", NULL },
	{ ".dcr",	"application/x-director",	"",		"", NULL },
	{ ".pac",	"application/x-ns-proxy-autoconfig", "",	"", NULL },
	{ ".pa",	"application/x-ns-proxy-autoconfig", "",	"", NULL },
	{ ".tar",	"multipart/x-tar",		"",		"", NULL },
	{ ".gtar",	"application/x-gtar-compressed", "",		"", NULL },
	{ ".tar.Z",	"application/x-gtar-compressed", "",		"", NULL },
	{ ".tar.gz",	"application/x-gtar-compressed", "",		"", NULL },
	{ ".taz",	"application/x-gtar-compressed", "",		"", NULL },
	{ ".tgz",	"application/x-gtar-compressed", "",		"", NULL },
	{ ".tar.z",	"application/x-gtar-compressed", "",		"", NULL },
	{ ".Z",		"application/x-compress",	"",		"", NULL },
	{ ".gz",	"application/x-gzip",		"",		"", NULL },
	{ ".z",		"unknown",			"",		"", NULL },
	{ ".bz2",	"application/x-bzip2",		"",		"", NULL },
	{ ".ogg",	"application/x-ogg",		"",		"", NULL },
	{ ".mkv",	"video/x-matroska",		"",		"", NULL },
	{ ".xbel",	"text/xml",			"",		"", NULL },
	{ ".xml",	"text/xml",			"",		"", NULL },
	{ ".xsl",	"text/xml",			"",		"", NULL },
	{ ".hqx",	"application/mac-binhex40",	"",		"", NULL },
	{ ".cpt",	"application/mac-compactpro",	"",		"", NULL },
	{ ".doc",	"application/msword",		"",		"", NULL },
	{ ".bin",	"application/octet-stream",	"",		"", NULL },
	{ ".dms",	"application/octet-stream",	"",		"", NULL },
	{ ".lha",	"application/octet-stream",	"",		"", NULL },
	{ ".lzh",	"application/octet-stream",	"",		"", NULL },
	{ ".exe",	"application/octet-stream",	"",		"", NULL },
	{ ".class",	"application/octet-stream",	"",		"", NULL },
	{ ".oda",	"application/oda",		"",		"", NULL },
	{ ".pdf",	"application/pdf",		"",		"", NULL },
	{ ".ai",	"application/postscript",	"",		"", NULL },
	{ ".eps",	"application/postscript",	"",		"", NULL },
	{ ".ps",	"application/postscript",	"",		"", NULL },
	{ ".ppt",	"application/powerpoint",	"",		"", NULL },
	{ ".rtf",	"application/rtf",		"",		"", NULL },
	{ ".bcpio",	"application/x-bcpio",		"",		"", NULL },
	{ ".torrent",	"application/x-bittorrent",	"",		"", NULL },
	{ ".vcd",	"application/x-cdlink",		"",		"", NULL },
	{ ".cpio",	"application/x-cpio",		"",		"", NULL },
	{ ".csh",	"application/x-csh",		"",		"", NULL },
	{ ".dir",	"application/x-director",	"",		"", NULL },
	{ ".dxr",	"application/x-director",	"",		"", NULL },
	{ ".dvi",	"application/x-dvi",		"",		"", NULL },
	{ ".hdf",	"application/x-hdf",		"",		"", NULL },
	{ ".cgi",	"application/x-httpd-cgi",	"",		"", NULL },
	{ ".skp",	"application/x-koan",		"",		"", NULL },
	{ ".skd",	"application/x-koan",		"",		"", NULL },
	{ ".skt",	"application/x-koan",		"",		"", NULL },
	{ ".skm",	"application/x-koan",		"",		"", NULL },
	{ ".latex",	"application/x-latex",		"",		"", NULL },
	{ ".mif",	"application/x-mif",		"",		"", NULL },
	{ ".nc",	"application/x-netcdf",		"",		"", NULL },
	{ ".cdf",	"application/x-netcdf",		"",		"", NULL },
	{ ".patch",	"application/x-patch",		"",		"", NULL },
	{ ".sh",	"application/x-sh",		"",		"", NULL },
	{ ".shar",	"application/x-shar",		"",		"", NULL },
	{ ".sit",	"application/x-stuffit",	"",		"", NULL },
	{ ".sv4cpio",	"application/x-sv4cpio",	"",		"", NULL },
	{ ".sv4crc",	"application/x-sv4crc",		"",		"", NULL },
	{ ".tar",	"application/x-tar",		"",		"", NULL },
	{ ".tcl",	"application/x-tcl",		"",		"", NULL },
	{ ".tex",	"application/x-tex",		"",		"", NULL },
	{ ".texinfo",	"application/x-texinfo",	"",		"", NULL },
	{ ".texi",	"application/x-texinfo",	"",		"", NULL },
	{ ".t",		"application/x-troff",		"",		"", NULL },
	{ ".tr",	"application/x-troff",		"",		"", NULL },
	{ ".roff",	"application/x-troff",		"",		"", NULL },
	{ ".man",	"application/x-troff-man",	"",		"", NULL },
	{ ".me",	"application/x-troff-me",	"",		"", NULL },
	{ ".ms",	"application/x-troff-ms",	"",		"", NULL },
	{ ".ustar",	"application/x-ustar",		"",		"", NULL },
	{ ".src",	"application/x-wais-source",	"",		"", NULL },
	{ ".zip",	"application/zip",		"",		"", NULL },
	{ ".au",	"audio/basic",			"",		"", NULL },
	{ ".snd",	"audio/basic",			"",		"", NULL },
	{ ".mpga",	"audio/mpeg",			"",		"", NULL },
	{ ".mp2",	"audio/mpeg",			"",		"", NULL },
	{ ".aif",	"audio/x-aiff",			"",		"", NULL },
	{ ".aiff",	"audio/x-aiff",			"",		"", NULL },
	{ ".aifc",	"audio/x-aiff",			"",		"", NULL },
	{ ".ram",	"audio/x-pn-realaudio",		"",		"", NULL },
	{ ".rpm",	"audio/x-pn-realaudio-plugin",	"",		"", NULL },
	{ ".ra",	"audio/x-realaudio",		"",		"", NULL },
	{ ".wav",	"audio/x-wav",			"",		"", NULL },
	{ ".pdb",	"chemical/x-pdb",		"",		"", NULL },
	{ ".xyz",	"chemical/x-pdb",		"",		"", NULL },
	{ ".ief",	"image/ief",			"",		"", NULL },
	{ ".tiff",	"image/tiff",			"",		"", NULL },
	{ ".tif",	"image/tiff",			"",		"", NULL },
	{ ".ras",	"image/x-cmu-raster",		"",		"", NULL },
	{ ".pnm",	"image/x-portable-anymap",	"",		"", NULL },
	{ ".pbm",	"image/x-portable-bitmap",	"",		"", NULL },
	{ ".pgm",	"image/x-portable-graymap",	"",		"", NULL },
	{ ".ppm",	"image/x-portable-pixmap",	"",		"", NULL },
	{ ".rgb",	"image/x-rgb",			"",		"", NULL },
	{ ".xbm",	"image/x-xbitmap",		"",		"", NULL },
	{ ".xpm",	"image/x-xpixmap",		"",		"", NULL },
	{ ".xwd",	"image/x-xwindowdump",		"",		"", NULL },
	{ ".rtx",	"text/richtext",		"",		"", NULL },
	{ ".tsv",	"text/tab-separated-values",	"",		"", NULL },
	{ ".etx",	"text/x-setext",		"",		"", NULL },
	{ ".sgml",	"text/x-sgml",			"",		"", NULL },
	{ ".sgm",	"text/x-sgml",			"",		"", NULL },
	{ ".mpeg",	"video/mpeg",			"",		"", NULL },
	{ ".mpg",	"video/mpeg",			"",		"", NULL },
	{ ".mpe",	"video/mpeg",			"",		"", NULL },
	{ ".ts",	"video/mpeg",			"",		"", NULL },
	{ ".vob",	"video/mpeg",			"",		"", NULL },
	{ ".mp4",	"video/mp4",			"",		"", NULL },
	{ ".qt",	"video/quicktime",		"",		"", NULL },
	{ ".mov",	"video/quicktime",		"",		"", NULL },
	{ ".avi",	"video/x-msvideo",		"",		"", NULL },
	{ ".movie",	"video/x-sgi-movie",		"",		"", NULL },
	{ ".ice",	"x-conference/x-cooltalk",	"",		"", NULL },
	{ ".wrl",	"x-world/x-vrml",		"",		"", NULL },
	{ ".vrml",	"x-world/x-vrml",		"",		"", NULL },
	{ ".svg",	"image/svg+xml",		"",		"", NULL },
	{ NULL,		NULL,		NULL,		NULL, NULL }
};

static bozo_content_map_t *
search_map(bozo_content_map_t *map, const char *name, size_t len)
{
	for ( ; map && map->name; map++) {
		const size_t namelen = strlen(map->name);
................................................................................
	httpd->dynamic_content_map = bozorealloc(httpd,
		httpd->dynamic_content_map,
		(httpd->dynamic_content_map_size + 1) * sizeof *map);
	if (httpd->dynamic_content_map == NULL)
		bozoerr(httpd, 1, "out of memory allocating content map");
	map = &httpd->dynamic_content_map[httpd->dynamic_content_map_size];
	map->name = map->type = map->encoding = map->encoding11 =
		map->cgihandler = NULL;
	map--;

	return map;
}

/*
 * mime content maps look like:
................................................................................
#define CHECKMAP(s)	(!s || ((s)[0] == '-' && (s)[1] == '\0') ? "" : (s))
	map->name = CHECKMAP(cmap0);
	map->type = CHECKMAP(cmap1);
	map->encoding = CHECKMAP(cmap2);
	map->encoding11 = CHECKMAP(cmap3);
#undef CHECKMAP
	map->cgihandler = NULL;

}
#endif /* NO_DYNAMIC_CONTENT */







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







 







|







 







>


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
...
293
294
295
296
297
298
299
300
301
302
 * this map and the functions below map between filenames and the
 * content type and content encoding definitions.  this should become
 * a configuration file, perhaps like apache's mime.types (but that
 * has less info per-entry).
 */

static bozo_content_map_t static_content_map[] = {
	{ ".html",	"text/html",			"",		"", NULL, NULL},
	{ ".htm",	"text/html",			"",		"", NULL, NULL},
	{ ".gif",	"image/gif",			"",		"", NULL, NULL},
	{ ".jpeg",	"image/jpeg",			"",		"", NULL, NULL},
	{ ".jpg",	"image/jpeg",			"",		"", NULL, NULL},
	{ ".jpe",	"image/jpeg",			"",		"", NULL, NULL},
	{ ".png",	"image/png",			"",		"", NULL, NULL},
	{ ".mp3",	"audio/mpeg",			"",		"", NULL, NULL},
	{ ".css",	"text/css",			"",		"", NULL, NULL},
	{ ".txt",	"text/plain",			"",		"", NULL, NULL},
	{ ".swf",	"application/x-shockwave-flash","",		"", NULL, NULL},
	{ ".dcr",	"application/x-director",	"",		"", NULL, NULL},
	{ ".pac",	"application/x-ns-proxy-autoconfig", "",	"", NULL, NULL},
	{ ".pa",	"application/x-ns-proxy-autoconfig", "",	"", NULL, NULL},
	{ ".tar",	"multipart/x-tar",		"",		"", NULL, NULL},
	{ ".gtar",	"application/x-gtar-compressed", "",		"", NULL, NULL},
	{ ".tar.Z",	"application/x-gtar-compressed", "",		"", NULL, NULL},
	{ ".tar.gz",	"application/x-gtar-compressed", "",		"", NULL, NULL},
	{ ".taz",	"application/x-gtar-compressed", "",		"", NULL, NULL},
	{ ".tgz",	"application/x-gtar-compressed", "",		"", NULL, NULL},
	{ ".tar.z",	"application/x-gtar-compressed", "",		"", NULL, NULL},
	{ ".Z",		"application/x-compress",	"",		"", NULL, NULL},
	{ ".gz",	"application/x-gzip",		"",		"", NULL, NULL},
	{ ".z",		"unknown",			"",		"", NULL, NULL},
	{ ".bz2",	"application/x-bzip2",		"",		"", NULL, NULL},
	{ ".ogg",	"application/x-ogg",		"",		"", NULL, NULL},
	{ ".mkv",	"video/x-matroska",		"",		"", NULL, NULL},
	{ ".xbel",	"text/xml",			"",		"", NULL, NULL},
	{ ".xml",	"text/xml",			"",		"", NULL, NULL},
	{ ".xsl",	"text/xml",			"",		"", NULL, NULL},
	{ ".hqx",	"application/mac-binhex40",	"",		"", NULL, NULL},
	{ ".cpt",	"application/mac-compactpro",	"",		"", NULL, NULL},
	{ ".doc",	"application/msword",		"",		"", NULL, NULL},
	{ ".bin",	"application/octet-stream",	"",		"", NULL, NULL},
	{ ".dms",	"application/octet-stream",	"",		"", NULL, NULL},
	{ ".lha",	"application/octet-stream",	"",		"", NULL, NULL},
	{ ".lzh",	"application/octet-stream",	"",		"", NULL, NULL},
	{ ".exe",	"application/octet-stream",	"",		"", NULL, NULL},
	{ ".class",	"application/octet-stream",	"",		"", NULL, NULL},
	{ ".oda",	"application/oda",		"",		"", NULL, NULL},
	{ ".pdf",	"application/pdf",		"",		"", NULL, NULL},
	{ ".ai",	"application/postscript",	"",		"", NULL, NULL},
	{ ".eps",	"application/postscript",	"",		"", NULL, NULL},
	{ ".ps",	"application/postscript",	"",		"", NULL, NULL},
	{ ".ppt",	"application/powerpoint",	"",		"", NULL, NULL},
	{ ".rtf",	"application/rtf",		"",		"", NULL, NULL},
	{ ".bcpio",	"application/x-bcpio",		"",		"", NULL, NULL},
	{ ".torrent",	"application/x-bittorrent",	"",		"", NULL, NULL},
	{ ".vcd",	"application/x-cdlink",		"",		"", NULL, NULL},
	{ ".cpio",	"application/x-cpio",		"",		"", NULL, NULL},
	{ ".csh",	"application/x-csh",		"",		"", NULL, NULL},
	{ ".dir",	"application/x-director",	"",		"", NULL, NULL},
	{ ".dxr",	"application/x-director",	"",		"", NULL, NULL},
	{ ".dvi",	"application/x-dvi",		"",		"", NULL, NULL},
	{ ".hdf",	"application/x-hdf",		"",		"", NULL, NULL},
	{ ".cgi",	"application/x-httpd-cgi",	"",		"", NULL, NULL},
	{ ".skp",	"application/x-koan",		"",		"", NULL, NULL},
	{ ".skd",	"application/x-koan",		"",		"", NULL, NULL},
	{ ".skt",	"application/x-koan",		"",		"", NULL, NULL},
	{ ".skm",	"application/x-koan",		"",		"", NULL, NULL},
	{ ".latex",	"application/x-latex",		"",		"", NULL, NULL},
	{ ".mif",	"application/x-mif",		"",		"", NULL, NULL},
	{ ".nc",	"application/x-netcdf",		"",		"", NULL, NULL},
	{ ".cdf",	"application/x-netcdf",		"",		"", NULL, NULL},
	{ ".patch",	"application/x-patch",		"",		"", NULL, NULL},
	{ ".sh",	"application/x-sh",		"",		"", NULL, NULL},
	{ ".shar",	"application/x-shar",		"",		"", NULL, NULL},
	{ ".sit",	"application/x-stuffit",	"",		"", NULL, NULL},
	{ ".sv4cpio",	"application/x-sv4cpio",	"",		"", NULL, NULL},
	{ ".sv4crc",	"application/x-sv4crc",		"",		"", NULL, NULL},
	{ ".tar",	"application/x-tar",		"",		"", NULL, NULL},
	{ ".tcl",	"application/x-tcl",		"",		"", NULL, NULL},
	{ ".tex",	"application/x-tex",		"",		"", NULL, NULL},
	{ ".texinfo",	"application/x-texinfo",	"",		"", NULL, NULL},
	{ ".texi",	"application/x-texinfo",	"",		"", NULL, NULL},
	{ ".t",		"application/x-troff",		"",		"", NULL, NULL},
	{ ".tr",	"application/x-troff",		"",		"", NULL, NULL},
	{ ".roff",	"application/x-troff",		"",		"", NULL, NULL},
	{ ".man",	"application/x-troff-man",	"",		"", NULL, NULL},
	{ ".me",	"application/x-troff-me",	"",		"", NULL, NULL},
	{ ".ms",	"application/x-troff-ms",	"",		"", NULL, NULL},
	{ ".ustar",	"application/x-ustar",		"",		"", NULL, NULL},
	{ ".src",	"application/x-wais-source",	"",		"", NULL, NULL},
	{ ".zip",	"application/zip",		"",		"", NULL, NULL},
	{ ".au",	"audio/basic",			"",		"", NULL, NULL},
	{ ".snd",	"audio/basic",			"",		"", NULL, NULL},
	{ ".mpga",	"audio/mpeg",			"",		"", NULL, NULL},
	{ ".mp2",	"audio/mpeg",			"",		"", NULL, NULL},
	{ ".aif",	"audio/x-aiff",			"",		"", NULL, NULL},
	{ ".aiff",	"audio/x-aiff",			"",		"", NULL, NULL},
	{ ".aifc",	"audio/x-aiff",			"",		"", NULL, NULL},
	{ ".ram",	"audio/x-pn-realaudio",		"",		"", NULL, NULL},
	{ ".rpm",	"audio/x-pn-realaudio-plugin",	"",		"", NULL, NULL},
	{ ".ra",	"audio/x-realaudio",		"",		"", NULL, NULL},
	{ ".wav",	"audio/x-wav",			"",		"", NULL, NULL},
	{ ".pdb",	"chemical/x-pdb",		"",		"", NULL, NULL},
	{ ".xyz",	"chemical/x-pdb",		"",		"", NULL, NULL},
	{ ".ief",	"image/ief",			"",		"", NULL, NULL},
	{ ".tiff",	"image/tiff",			"",		"", NULL, NULL},
	{ ".tif",	"image/tiff",			"",		"", NULL, NULL},
	{ ".ras",	"image/x-cmu-raster",		"",		"", NULL, NULL},
	{ ".pnm",	"image/x-portable-anymap",	"",		"", NULL, NULL},
	{ ".pbm",	"image/x-portable-bitmap",	"",		"", NULL, NULL},
	{ ".pgm",	"image/x-portable-graymap",	"",		"", NULL, NULL},
	{ ".ppm",	"image/x-portable-pixmap",	"",		"", NULL, NULL},
	{ ".rgb",	"image/x-rgb",			"",		"", NULL, NULL},
	{ ".xbm",	"image/x-xbitmap",		"",		"", NULL, NULL},
	{ ".xpm",	"image/x-xpixmap",		"",		"", NULL, NULL},
	{ ".xwd",	"image/x-xwindowdump",		"",		"", NULL, NULL},
	{ ".rtx",	"text/richtext",		"",		"", NULL, NULL},
	{ ".tsv",	"text/tab-separated-values",	"",		"", NULL, NULL},
	{ ".etx",	"text/x-setext",		"",		"", NULL, NULL},
	{ ".sgml",	"text/x-sgml",			"",		"", NULL, NULL},
	{ ".sgm",	"text/x-sgml",			"",		"", NULL, NULL},
	{ ".mpeg",	"video/mpeg",			"",		"", NULL, NULL},
	{ ".mpg",	"video/mpeg",			"",		"", NULL, NULL},
	{ ".mpe",	"video/mpeg",			"",		"", NULL, NULL},
	{ ".ts",	"video/mpeg",			"",		"", NULL, NULL},
	{ ".vob",	"video/mpeg",			"",		"", NULL, NULL},
	{ ".mp4",	"video/mp4",			"",		"", NULL, NULL},
	{ ".qt",	"video/quicktime",		"",		"", NULL, NULL},
	{ ".mov",	"video/quicktime",		"",		"", NULL, NULL},
	{ ".avi",	"video/x-msvideo",		"",		"", NULL, NULL},
	{ ".movie",	"video/x-sgi-movie",		"",		"", NULL, NULL},
	{ ".ice",	"x-conference/x-cooltalk",	"",		"", NULL, NULL},
	{ ".wrl",	"x-world/x-vrml",		"",		"", NULL, NULL},
	{ ".vrml",	"x-world/x-vrml",		"",		"", NULL, NULL},
	{ ".svg",	"image/svg+xml",		"",		"", NULL, NULL},
	{ NULL,		NULL,		NULL,		NULL, NULL, NULL}
};

static bozo_content_map_t *
search_map(bozo_content_map_t *map, const char *name, size_t len)
{
	for ( ; map && map->name; map++) {
		const size_t namelen = strlen(map->name);
................................................................................
	httpd->dynamic_content_map = bozorealloc(httpd,
		httpd->dynamic_content_map,
		(httpd->dynamic_content_map_size + 1) * sizeof *map);
	if (httpd->dynamic_content_map == NULL)
		bozoerr(httpd, 1, "out of memory allocating content map");
	map = &httpd->dynamic_content_map[httpd->dynamic_content_map_size];
	map->name = map->type = map->encoding = map->encoding11 =
		map->cgihandler = map->cacheheader = NULL;
	map--;

	return map;
}

/*
 * mime content maps look like:
................................................................................
#define CHECKMAP(s)	(!s || ((s)[0] == '-' && (s)[1] == '\0') ? "" : (s))
	map->name = CHECKMAP(cmap0);
	map->type = CHECKMAP(cmap1);
	map->encoding = CHECKMAP(cmap2);
	map->encoding11 = CHECKMAP(cmap3);
#undef CHECKMAP
	map->cgihandler = NULL;
	map->cacheheader = NULL;
}
#endif /* NO_DYNAMIC_CONTENT */

Changes to dir-index-bozo.c.

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
		goto done;
		/* NOTREACHED */
	}

	bozo_printf(httpd, "%s 200 OK\r\n", request->hr_proto);

	if (request->hr_proto != httpd->consts.http_09) {
		bozo_print_header(request, NULL, "text/html", "");
		bozo_printf(httpd, "\r\n");
	}
	bozo_flush(httpd, stdout);

	if (request->hr_method == HTTP_HEAD) {
		closedir(dp);
		goto done;







|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
		goto done;
		/* NOTREACHED */
	}

	bozo_printf(httpd, "%s 200 OK\r\n", request->hr_proto);

	if (request->hr_proto != httpd->consts.http_09) {
		bozo_print_header(request, NULL, "text/html", "", NULL);
		bozo_printf(httpd, "\r\n");
	}
	bozo_flush(httpd, stdout);

	if (request->hr_method == HTTP_HEAD) {
		closedir(dp);
		goto done;

Changes to main.c.

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
191
192
193
194
195
196
197
198
199


200
201
202
203
204
205
206
	bozowarn(httpd, "   -b\t\t\tbackground and go into daemon mode");
	bozowarn(httpd, "   -f\t\t\tkeep daemon mode in the foreground");
	bozowarn(httpd,
		"   -i address\t\tbind on this address (daemon mode only)");
	bozowarn(httpd, "   -P pidfile\t\tpath to the pid file to create");
#endif
	bozowarn(httpd, "   -S version\t\tset server version string");
	bozowarn(httpd, "   -h string\t\tCache-Control headers");
	bozowarn(httpd, "   -t dir\t\tchroot to `dir'");
	bozowarn(httpd, "   -U username\t\tchange user to `user'");
	bozowarn(httpd,
		"   -e\t\t\tdon't clean the environment (-t and -U only)");
	bozowarn(httpd,
		"   -v virtualroot\tenable virtual host support "
		"in this directory");
................................................................................
			break;

		case 'S':
			bozo_set_pref(&httpd, &prefs, "server software",
				      optarg);
			break;
		case 'h':
			bozo_set_pref(&httpd, &prefs, "Cache-Control headers",
				      optarg);


			break;
		case 'Z':
#ifdef NO_SSL_SUPPORT
			bozoerr(&httpd, 1, "ssl support is not enabled");
			/* NOT REACHED */
#else
			/* make sure there's two arguments */







|







 







|
|
>
>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
	bozowarn(httpd, "   -b\t\t\tbackground and go into daemon mode");
	bozowarn(httpd, "   -f\t\t\tkeep daemon mode in the foreground");
	bozowarn(httpd,
		"   -i address\t\tbind on this address (daemon mode only)");
	bozowarn(httpd, "   -P pidfile\t\tpath to the pid file to create");
#endif
	bozowarn(httpd, "   -S version\t\tset server version string");
	bozowarn(httpd, "   -h arg header\tAdd Cache-Control header for filename suffix");
	bozowarn(httpd, "   -t dir\t\tchroot to `dir'");
	bozowarn(httpd, "   -U username\t\tchange user to `user'");
	bozowarn(httpd,
		"   -e\t\t\tdon't clean the environment (-t and -U only)");
	bozowarn(httpd,
		"   -v virtualroot\tenable virtual host support "
		"in this directory");
................................................................................
			break;

		case 'S':
			bozo_set_pref(&httpd, &prefs, "server software",
				      optarg);
			break;
		case 'h':
			/* make sure there's two arguments */
			if (argc - optind < 1)
				usage(&httpd, progname);
			bozo_add_content_map_cache(&httpd, optarg, argv[optind++]);
			break;
		case 'Z':
#ifdef NO_SSL_SUPPORT
			bozoerr(&httpd, 1, "ssl support is not enabled");
			/* NOT REACHED */
#else
			/* make sure there's two arguments */