version 1.28, 2011/08/27 15:33:59 |
version 1.28.2.2, 2012/10/30 18:59:22 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
|
/* $eterna: bozohttpd.c,v 1.176 2010/09/20 22:26:28 mrg Exp $ */ |
/* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1997-2010 Matthew R. Green |
* Copyright (c) 1997-2011 Matthew R. Green |
* All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
|
|
#define INDEX_HTML "index.html" |
#define INDEX_HTML "index.html" |
#endif |
#endif |
#ifndef SERVER_SOFTWARE |
#ifndef SERVER_SOFTWARE |
#define SERVER_SOFTWARE "bozohttpd/20100920" |
#define SERVER_SOFTWARE "bozohttpd/20111118" |
#endif |
#endif |
#ifndef DIRECT_ACCESS_FILE |
#ifndef DIRECT_ACCESS_FILE |
#define DIRECT_ACCESS_FILE ".bzdirect" |
#define DIRECT_ACCESS_FILE ".bzdirect" |
Line 563 bozo_read_request(bozohttpd_t *httpd) |
|
Line 563 bozo_read_request(bozohttpd_t *httpd) |
|
if (addr != NULL) |
if (addr != NULL) |
request->hr_remoteaddr = bozostrdup(request->hr_httpd, addr); |
request->hr_remoteaddr = bozostrdup(request->hr_httpd, addr); |
slen = sizeof(ss); |
slen = sizeof(ss); |
if (getsockname(0, (struct sockaddr *)(void *)&ss, &slen) < 0) |
|
port = NULL; |
/* |
else { |
* Override the bound port from the request value, so it works even |
if (getnameinfo((struct sockaddr *)(void *)&ss, slen, NULL, 0, |
* if passed through a proxy that doesn't rewrite the port. |
bufport, sizeof bufport, NI_NUMERICSERV) == 0) |
*/ |
port = bufport; |
if (httpd->bindport) { |
|
if (strcmp(httpd->bindport, "80") != 0) |
|
port = httpd->bindport; |
else |
else |
port = NULL; |
port = NULL; |
|
} else { |
|
if (getsockname(0, (struct sockaddr *)(void *)&ss, &slen) < 0) |
|
port = NULL; |
|
else { |
|
if (getnameinfo((struct sockaddr *)(void *)&ss, slen, NULL, 0, |
|
bufport, sizeof bufport, NI_NUMERICSERV) == 0) |
|
port = bufport; |
|
else |
|
port = NULL; |
|
} |
} |
} |
if (port != NULL) |
if (port != NULL) |
request->hr_serverport = bozostrdup(request->hr_httpd, port); |
request->hr_serverport = bozostrdup(request->hr_httpd, port); |
Line 684 bozo_read_request(bozohttpd_t *httpd) |
|
Line 696 bozo_read_request(bozohttpd_t *httpd) |
|
else if (strcasecmp(hdr->h_header, |
else if (strcasecmp(hdr->h_header, |
"if-modified-since") == 0) |
"if-modified-since") == 0) |
request->hr_if_modified_since = hdr->h_value; |
request->hr_if_modified_since = hdr->h_value; |
|
else if (strcasecmp(hdr->h_header, |
|
"accept-encoding") == 0) |
|
request->hr_accept_encoding = hdr->h_value; |
|
|
debug((httpd, DEBUG_FAT, "adding header %s: %s", |
debug((httpd, DEBUG_FAT, "adding header %s: %s", |
hdr->h_header, hdr->h_value)); |
hdr->h_header, hdr->h_value)); |
Line 832 parse_http_date(const char *val, time_t |
|
Line 847 parse_http_date(const char *val, time_t |
|
} |
} |
|
|
/* |
/* |
|
* given an url, encode it ala rfc 3986. ie, escape ? and friends. |
|
* note that this function returns a static buffer, and thus needs |
|
* to be updated for any sort of parallel processing. |
|
*/ |
|
char * |
|
escape_rfc3986(bozohttpd_t *httpd, const char *url) |
|
{ |
|
static char *buf; |
|
static size_t buflen = 0; |
|
size_t len; |
|
const char *s; |
|
char *d; |
|
|
|
len = strlen(url); |
|
if (buflen < len * 3 + 1) { |
|
buflen = len * 3 + 1; |
|
buf = bozorealloc(httpd, buf, buflen); |
|
} |
|
|
|
if (url == NULL) { |
|
buf[0] = 0; |
|
return buf; |
|
} |
|
|
|
for (s = url, d = buf; *s;) { |
|
if (*s & 0x80) |
|
goto encode_it; |
|
switch (*s) { |
|
case ':': |
|
case '/': |
|
case '?': |
|
case '#': |
|
case '[': |
|
case ']': |
|
case '@': |
|
case '!': |
|
case '$': |
|
case '&': |
|
case '\'': |
|
case '(': |
|
case ')': |
|
case '*': |
|
case '+': |
|
case ',': |
|
case ';': |
|
case '=': |
|
encode_it: |
|
snprintf(d, 4, "%%%2X", *s++); |
|
d += 3; |
|
len += 3; |
|
default: |
|
*d++ = *s++; |
|
len++; |
|
} |
|
} |
|
buf[len] = 0; |
|
|
|
return buf; |
|
} |
|
|
|
/* |
* checks to see if this request has a valid .bzdirect file. returns |
* checks to see if this request has a valid .bzdirect file. returns |
* 0 on failure and 1 on success. |
* 0 on failure and 1 on success. |
*/ |
*/ |
Line 883 handle_redirect(bozo_httpreq_t *request, |
|
Line 959 handle_redirect(bozo_httpreq_t *request, |
|
url = urlbuf; |
url = urlbuf; |
} else |
} else |
urlbuf = NULL; |
urlbuf = NULL; |
|
url = escape_rfc3986(request->hr_httpd, url); |
|
|
if (request->hr_query && strlen(request->hr_query)) { |
if (request->hr_query && strlen(request->hr_query)) |
query = 1; |
query = 1; |
} |
|
|
|
if (request->hr_serverport && strcmp(request->hr_serverport, "80") != 0) |
if (request->hr_serverport && strcmp(request->hr_serverport, "80") != 0) |
snprintf(portbuf, sizeof(portbuf), ":%s", |
snprintf(portbuf, sizeof(portbuf), ":%s", |
Line 903 handle_redirect(bozo_httpreq_t *request, |
|
Line 979 handle_redirect(bozo_httpreq_t *request, |
|
if (absolute == 0) |
if (absolute == 0) |
bozo_printf(httpd, "%s%s", httpd->virthostname, portbuf); |
bozo_printf(httpd, "%s%s", httpd->virthostname, portbuf); |
if (query) { |
if (query) { |
bozo_printf(httpd, "%s?%s\r\n", url, request->hr_query); |
bozo_printf(httpd, "%s?%s\r\n", url, request->hr_query); |
} else { |
} else { |
bozo_printf(httpd, "%s\r\n", url); |
bozo_printf(httpd, "%s\r\n", url); |
} |
} |
} |
} |
bozo_printf(httpd, "\r\n"); |
bozo_printf(httpd, "\r\n"); |
Line 915 handle_redirect(bozo_httpreq_t *request, |
|
Line 991 handle_redirect(bozo_httpreq_t *request, |
|
bozo_printf(httpd, "<body><h1>Document Moved</h1>\n"); |
bozo_printf(httpd, "<body><h1>Document Moved</h1>\n"); |
bozo_printf(httpd, "This document had moved <a href=\"http://"); |
bozo_printf(httpd, "This document had moved <a href=\"http://"); |
if (query) { |
if (query) { |
if (absolute) |
if (absolute) |
bozo_printf(httpd, "%s?%s", url, request->hr_query); |
bozo_printf(httpd, "%s?%s", url, request->hr_query); |
else |
else |
bozo_printf(httpd, "%s%s%s?%s", httpd->virthostname, portbuf, url, |
bozo_printf(httpd, "%s%s%s?%s", httpd->virthostname, |
request->hr_query); |
portbuf, url, request->hr_query); |
} else { |
} else { |
if (absolute) |
if (absolute) |
bozo_printf(httpd, "%s", url); |
bozo_printf(httpd, "%s", url); |
else |
else |
bozo_printf(httpd, "%s%s%s", httpd->virthostname, portbuf, url); |
bozo_printf(httpd, "%s%s%s", httpd->virthostname, |
|
portbuf, url); |
} |
} |
bozo_printf(httpd, "\">here</a>\n"); |
bozo_printf(httpd, "\">here</a>\n"); |
bozo_printf(httpd, "</body></html>\n"); |
bozo_printf(httpd, "</body></html>\n"); |
|
|
} |
} |
|
|
/* |
/* |
|
* can_gzip checks if the request supports and prefers gzip encoding. |
|
* |
|
* XXX: we do not consider the associated q with gzip in making our |
|
* decision which is broken. |
|
*/ |
|
|
|
static int |
|
can_gzip(bozo_httpreq_t *request) |
|
{ |
|
const char *pos; |
|
const char *tmp; |
|
size_t len; |
|
|
|
/* First we decide if the request can be gzipped at all. */ |
|
|
|
/* not if we already are encoded... */ |
|
tmp = bozo_content_encoding(request, request->hr_file); |
|
if (tmp && *tmp) |
|
return 0; |
|
|
|
/* not if we are not asking for the whole file... */ |
|
if (request->hr_last_byte_pos != -1 || request->hr_have_range) |
|
return 0; |
|
|
|
/* Then we determine if gzip is on the cards. */ |
|
|
|
for (pos = request->hr_accept_encoding; pos && *pos; pos += len) { |
|
while (*pos == ' ') |
|
pos++; |
|
|
|
len = strcspn(pos, ";,"); |
|
|
|
if ((len == 4 && strncasecmp("gzip", pos, 4) == 0) || |
|
(len == 6 && strncasecmp("x-gzip", pos, 6) == 0)) |
|
return 1; |
|
|
|
if (pos[len] == ';') |
|
len += strcspn(&pos[len], ","); |
|
|
|
if (pos[len]) |
|
len++; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/* |
* bozo_process_request does the following: |
* bozo_process_request does the following: |
* - check the request is valid |
* - check the request is valid |
* - process cgi-bin if necessary |
* - process cgi-bin if necessary |
Line 1362 bozo_process_request(bozo_httpreq_t *req |
|
Line 1486 bozo_process_request(bozo_httpreq_t *req |
|
if (transform_request(request, &isindex) == 0) |
if (transform_request(request, &isindex) == 0) |
return; |
return; |
|
|
|
fd = -1; |
|
encoding = NULL; |
|
if (can_gzip(request)) { |
|
asprintf(&file, "%s.gz", request->hr_file); |
|
fd = open(file, O_RDONLY); |
|
if (fd >= 0) |
|
encoding = "gzip"; |
|
free(file); |
|
} |
|
|
file = request->hr_file; |
file = request->hr_file; |
|
|
fd = open(file, O_RDONLY); |
if (fd < 0) |
|
fd = open(file, O_RDONLY); |
|
|
if (fd < 0) { |
if (fd < 0) { |
debug((httpd, DEBUG_FAT, "open failed: %s", strerror(errno))); |
debug((httpd, DEBUG_FAT, "open failed: %s", strerror(errno))); |
if (errno == EPERM) |
if (errno == EPERM) |
Line 1420 bozo_process_request(bozo_httpreq_t *req |
|
Line 1556 bozo_process_request(bozo_httpreq_t *req |
|
|
|
if (request->hr_proto != httpd->consts.http_09) { |
if (request->hr_proto != httpd->consts.http_09) { |
type = bozo_content_type(request, file); |
type = bozo_content_type(request, file); |
encoding = bozo_content_encoding(request, file); |
if (!encoding) |
|
encoding = bozo_content_encoding(request, file); |
|
|
bozo_print_header(request, &sb, type, encoding); |
bozo_print_header(request, &sb, type, encoding); |
bozo_printf(httpd, "\r\n"); |
bozo_printf(httpd, "\r\n"); |