mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
uri -> url
This commit is contained in:
parent
597c81d3f1
commit
010d194180
120
darkhttpd.c
120
darkhttpd.c
@ -213,7 +213,7 @@ struct connection {
|
|||||||
size_t request_length;
|
size_t request_length;
|
||||||
|
|
||||||
/* request fields */
|
/* request fields */
|
||||||
char *method, *uri, *referer, *user_agent;
|
char *method, *url, *referer, *user_agent;
|
||||||
off_t range_begin, range_end;
|
off_t range_begin, range_end;
|
||||||
off_t range_begin_given, range_end_given;
|
off_t range_begin_given, range_end_given;
|
||||||
|
|
||||||
@ -478,47 +478,47 @@ static void consolidate_slashes(char *s) {
|
|||||||
s[left] = '\0';
|
s[left] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve /./ and /../ in a URI, in-place. Returns NULL if the URI is
|
/* Resolve /./ and /../ in a URL, in-place. Returns NULL if the URL is
|
||||||
* invalid/unsafe, or the original buffer if successful.
|
* invalid/unsafe, or the original buffer if successful.
|
||||||
*/
|
*/
|
||||||
static char *make_safe_uri(char *uri) {
|
static char *make_safe_url(char *url) {
|
||||||
struct {
|
struct {
|
||||||
char *start;
|
char *start;
|
||||||
size_t len;
|
size_t len;
|
||||||
} *chunks;
|
} *chunks;
|
||||||
unsigned int num_slashes, num_chunks;
|
unsigned int num_slashes, num_chunks;
|
||||||
size_t urilen, i, j, pos;
|
size_t urllen, i, j, pos;
|
||||||
int ends_in_slash;
|
int ends_in_slash;
|
||||||
|
|
||||||
assert(uri != NULL);
|
assert(url != NULL);
|
||||||
if (uri[0] != '/')
|
if (url[0] != '/')
|
||||||
return NULL;
|
return NULL;
|
||||||
consolidate_slashes(uri);
|
consolidate_slashes(url);
|
||||||
urilen = strlen(uri);
|
urllen = strlen(url);
|
||||||
if (urilen > 0)
|
if (urllen > 0)
|
||||||
ends_in_slash = (uri[urilen-1] == '/');
|
ends_in_slash = (url[urllen-1] == '/');
|
||||||
else
|
else
|
||||||
ends_in_slash = 1;
|
ends_in_slash = 1;
|
||||||
|
|
||||||
/* count the slashes */
|
/* count the slashes */
|
||||||
for (i=0, num_slashes=0; i<urilen; i++)
|
for (i=0, num_slashes=0; i<urllen; i++)
|
||||||
if (uri[i] == '/')
|
if (url[i] == '/')
|
||||||
num_slashes++;
|
num_slashes++;
|
||||||
|
|
||||||
/* make an array for the URI elements */
|
/* make an array for the URL elements */
|
||||||
chunks = xmalloc(sizeof(*chunks) * num_slashes);
|
chunks = xmalloc(sizeof(*chunks) * num_slashes);
|
||||||
|
|
||||||
/* split by slashes and build chunks array */
|
/* split by slashes and build chunks array */
|
||||||
num_chunks = 0;
|
num_chunks = 0;
|
||||||
for (i=1; i<urilen;) {
|
for (i=1; i<urllen;) {
|
||||||
/* look for the next slash */
|
/* look for the next slash */
|
||||||
for (j=i; j<urilen && uri[j] != '/'; j++)
|
for (j=i; j<urllen && url[j] != '/'; j++)
|
||||||
;
|
;
|
||||||
|
|
||||||
/* process uri[i,j) */
|
/* process url[i,j) */
|
||||||
if ((j == i+1) && (uri[i] == '.'))
|
if ((j == i+1) && (url[i] == '.'))
|
||||||
/* "." */;
|
/* "." */;
|
||||||
else if ((j == i+2) && (uri[i] == '.') && (uri[i+1] == '.')) {
|
else if ((j == i+2) && (url[i] == '.') && (url[i+1] == '.')) {
|
||||||
/* ".." */
|
/* ".." */
|
||||||
if (num_chunks == 0) {
|
if (num_chunks == 0) {
|
||||||
/* unsafe string so free chunks */
|
/* unsafe string so free chunks */
|
||||||
@ -527,34 +527,34 @@ static char *make_safe_uri(char *uri) {
|
|||||||
} else
|
} else
|
||||||
num_chunks--;
|
num_chunks--;
|
||||||
} else {
|
} else {
|
||||||
chunks[num_chunks].start = uri+i;
|
chunks[num_chunks].start = url+i;
|
||||||
chunks[num_chunks].len = j-i;
|
chunks[num_chunks].len = j-i;
|
||||||
num_chunks++;
|
num_chunks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = j + 1; /* uri[j] is a slash - move along one */
|
i = j + 1; /* url[j] is a slash - move along one */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reassemble in-place */
|
/* reassemble in-place */
|
||||||
pos = 0;
|
pos = 0;
|
||||||
for (i=0; i<num_chunks; i++) {
|
for (i=0; i<num_chunks; i++) {
|
||||||
assert(pos <= urilen);
|
assert(pos <= urllen);
|
||||||
uri[pos++] = '/';
|
url[pos++] = '/';
|
||||||
|
|
||||||
assert(pos + chunks[i].len <= urilen);
|
assert(pos + chunks[i].len <= urllen);
|
||||||
assert(uri + pos <= chunks[i].start);
|
assert(url + pos <= chunks[i].start);
|
||||||
|
|
||||||
if (uri+pos < chunks[i].start)
|
if (url+pos < chunks[i].start)
|
||||||
memmove(uri+pos, chunks[i].start, chunks[i].len);
|
memmove(url+pos, chunks[i].start, chunks[i].len);
|
||||||
pos += chunks[i].len;
|
pos += chunks[i].len;
|
||||||
}
|
}
|
||||||
free(chunks);
|
free(chunks);
|
||||||
|
|
||||||
if ((num_chunks == 0) || ends_in_slash)
|
if ((num_chunks == 0) || ends_in_slash)
|
||||||
uri[pos++] = '/';
|
url[pos++] = '/';
|
||||||
assert(pos <= urilen);
|
assert(pos <= urllen);
|
||||||
uri[pos] = '\0';
|
url[pos] = '\0';
|
||||||
return uri;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Associates an extension with a mimetype in the mime_map. Entries are in
|
/* Associates an extension with a mimetype in the mime_map. Entries are in
|
||||||
@ -742,7 +742,7 @@ static void parse_extension_map_file(const char *filename) {
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Uses the mime_map to determine a Content-Type: for a requested URI. This
|
/* Uses the mime_map to determine a Content-Type: for a requested URL. This
|
||||||
* bsearch()es mime_map, so make sure it's sorted first.
|
* bsearch()es mime_map, so make sure it's sorted first.
|
||||||
*/
|
*/
|
||||||
static int mime_mapping_cmp_str(const void *a, const void *b) {
|
static int mime_mapping_cmp_str(const void *a, const void *b) {
|
||||||
@ -750,21 +750,21 @@ static int mime_mapping_cmp_str(const void *a, const void *b) {
|
|||||||
((const struct mime_mapping *)b)->extension);
|
((const struct mime_mapping *)b)->extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *uri_content_type(const char *uri) {
|
static const char *url_content_type(const char *url) {
|
||||||
int period, urilen = (int)strlen(uri);
|
int period, urllen = (int)strlen(url);
|
||||||
|
|
||||||
for (period = urilen - 1;
|
for (period = urllen - 1;
|
||||||
(period > 0) && (uri[period] != '.') &&
|
(period > 0) && (url[period] != '.') &&
|
||||||
(urilen - period - 1 <= (int)longest_ext);
|
(urllen - period - 1 <= (int)longest_ext);
|
||||||
period--)
|
period--)
|
||||||
;
|
;
|
||||||
|
|
||||||
if ((period >= 0) && (uri[period] == '.')) {
|
if ((period >= 0) && (url[period] == '.')) {
|
||||||
struct mime_mapping *result =
|
struct mime_mapping *result =
|
||||||
bsearch((uri + period + 1), mime_map, mime_map_size,
|
bsearch((url + period + 1), mime_map, mime_map_size,
|
||||||
sizeof(struct mime_mapping), mime_mapping_cmp_str);
|
sizeof(struct mime_mapping), mime_mapping_cmp_str);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(strcmp(uri + period + 1, result->extension) == 0);
|
assert(strcmp(url + period + 1, result->extension) == 0);
|
||||||
return result->mimetype;
|
return result->mimetype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1012,7 +1012,7 @@ static struct connection *new_connection(void) {
|
|||||||
conn->request = NULL;
|
conn->request = NULL;
|
||||||
conn->request_length = 0;
|
conn->request_length = 0;
|
||||||
conn->method = NULL;
|
conn->method = NULL;
|
||||||
conn->uri = NULL;
|
conn->url = NULL;
|
||||||
conn->referer = NULL;
|
conn->referer = NULL;
|
||||||
conn->user_agent = NULL;
|
conn->user_agent = NULL;
|
||||||
conn->range_begin = 0;
|
conn->range_begin = 0;
|
||||||
@ -1085,14 +1085,14 @@ static void log_connection(const struct connection *conn) {
|
|||||||
return; /* invalid - didn't parse - maybe too long */
|
return; /* invalid - didn't parse - maybe too long */
|
||||||
|
|
||||||
/* Separated by tabs:
|
/* Separated by tabs:
|
||||||
* time client_ip method uri http_code bytes_sent "referer" "user-agent"
|
* time client_ip method url http_code bytes_sent "referer" "user-agent"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inaddr.s_addr = conn->client;
|
inaddr.s_addr = conn->client;
|
||||||
|
|
||||||
fprintf(logfile, "%lu\t%s\t%s\t%s\t%d\t%llu\t\"%s\"\t\"%s\"\n",
|
fprintf(logfile, "%lu\t%s\t%s\t%s\t%d\t%llu\t\"%s\"\t\"%s\"\n",
|
||||||
(unsigned long int)now, inet_ntoa(inaddr),
|
(unsigned long int)now, inet_ntoa(inaddr),
|
||||||
conn->method, conn->uri,
|
conn->method, conn->url,
|
||||||
conn->http_code, llu(conn->total_sent),
|
conn->http_code, llu(conn->total_sent),
|
||||||
(conn->referer == NULL)?"":conn->referer,
|
(conn->referer == NULL)?"":conn->referer,
|
||||||
(conn->user_agent == NULL)?"":conn->user_agent
|
(conn->user_agent == NULL)?"":conn->user_agent
|
||||||
@ -1107,7 +1107,7 @@ static void free_connection(struct connection *conn) {
|
|||||||
if (conn->socket != -1) xclose(conn->socket);
|
if (conn->socket != -1) xclose(conn->socket);
|
||||||
if (conn->request != NULL) free(conn->request);
|
if (conn->request != NULL) free(conn->request);
|
||||||
if (conn->method != NULL) free(conn->method);
|
if (conn->method != NULL) free(conn->method);
|
||||||
if (conn->uri != NULL) free(conn->uri);
|
if (conn->url != NULL) free(conn->url);
|
||||||
if (conn->referer != NULL) free(conn->referer);
|
if (conn->referer != NULL) free(conn->referer);
|
||||||
if (conn->user_agent != NULL) free(conn->user_agent);
|
if (conn->user_agent != NULL) free(conn->user_agent);
|
||||||
if (conn->header != NULL && !conn->header_dont_free) free(conn->header);
|
if (conn->header != NULL && !conn->header_dont_free) free(conn->header);
|
||||||
@ -1128,7 +1128,7 @@ static void recycle_connection(struct connection *conn) {
|
|||||||
conn->request = NULL;
|
conn->request = NULL;
|
||||||
conn->request_length = 0;
|
conn->request_length = 0;
|
||||||
conn->method = NULL;
|
conn->method = NULL;
|
||||||
conn->uri = NULL;
|
conn->url = NULL;
|
||||||
conn->referer = NULL;
|
conn->referer = NULL;
|
||||||
conn->user_agent = NULL;
|
conn->user_agent = NULL;
|
||||||
conn->range_begin = 0;
|
conn->range_begin = 0;
|
||||||
@ -1396,7 +1396,7 @@ static int parse_request(struct connection *conn) {
|
|||||||
conn->method = split_string(conn->request, 0, bound1);
|
conn->method = split_string(conn->request, 0, bound1);
|
||||||
strntoupper(conn->method, bound1);
|
strntoupper(conn->method, bound1);
|
||||||
|
|
||||||
/* parse uri */
|
/* parse url */
|
||||||
for (;
|
for (;
|
||||||
(bound1 < conn->request_length) &&
|
(bound1 < conn->request_length) &&
|
||||||
(conn->request[bound1] == ' ');
|
(conn->request[bound1] == ' ');
|
||||||
@ -1414,7 +1414,7 @@ static int parse_request(struct connection *conn) {
|
|||||||
bound2++)
|
bound2++)
|
||||||
;
|
;
|
||||||
|
|
||||||
conn->uri = split_string(conn->request, bound1, bound2);
|
conn->url = split_string(conn->request, bound1, bound2);
|
||||||
|
|
||||||
/* parse protocol to determine conn_close */
|
/* parse protocol to determine conn_close */
|
||||||
if (conn->request[bound2] == ' ') {
|
if (conn->request[bound2] == ' ') {
|
||||||
@ -1590,9 +1590,9 @@ static void generate_dir_listing(struct connection *conn, const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
append(listing, "<html>\n<head>\n <title>");
|
append(listing, "<html>\n<head>\n <title>");
|
||||||
append(listing, conn->uri);
|
append(listing, conn->url);
|
||||||
append(listing, "</title>\n</head>\n<body>\n<h1>");
|
append(listing, "</title>\n</head>\n<body>\n<h1>");
|
||||||
append(listing, conn->uri);
|
append(listing, conn->url);
|
||||||
append(listing, "</h1>\n<tt><pre>\n");
|
append(listing, "</h1>\n<tt><pre>\n");
|
||||||
|
|
||||||
spaces = xmalloc(maxlen);
|
spaces = xmalloc(maxlen);
|
||||||
@ -1660,12 +1660,12 @@ static void process_get(struct connection *conn) {
|
|||||||
struct stat filestat;
|
struct stat filestat;
|
||||||
|
|
||||||
/* work out path of file being requested */
|
/* work out path of file being requested */
|
||||||
decoded_url = urldecode(conn->uri);
|
decoded_url = urldecode(conn->url);
|
||||||
|
|
||||||
/* make sure it's safe */
|
/* make sure it's safe */
|
||||||
if (make_safe_uri(decoded_url) == NULL) {
|
if (make_safe_url(decoded_url) == NULL) {
|
||||||
default_reply(conn, 400, "Bad Request",
|
default_reply(conn, 400, "Bad Request",
|
||||||
"You requested an invalid URI: %s", conn->uri);
|
"You requested an invalid URL: %s", conn->url);
|
||||||
free(decoded_url);
|
free(decoded_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1681,17 +1681,17 @@ static void process_get(struct connection *conn) {
|
|||||||
free(decoded_url);
|
free(decoded_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mimetype = uri_content_type(index_name);
|
mimetype = url_content_type(index_name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* points to a file */
|
/* points to a file */
|
||||||
xasprintf(&target, "%s%s", wwwroot, decoded_url);
|
xasprintf(&target, "%s%s", wwwroot, decoded_url);
|
||||||
mimetype = uri_content_type(decoded_url);
|
mimetype = url_content_type(decoded_url);
|
||||||
}
|
}
|
||||||
free(decoded_url);
|
free(decoded_url);
|
||||||
if (debug)
|
if (debug)
|
||||||
printf("uri=\"%s\", target=\"%s\", content-type=\"%s\"\n",
|
printf("url=\"%s\", target=\"%s\", content-type=\"%s\"\n",
|
||||||
conn->uri, target, mimetype);
|
conn->url, target, mimetype);
|
||||||
|
|
||||||
/* open file */
|
/* open file */
|
||||||
conn->reply_fd = open(target, O_RDONLY | O_NONBLOCK);
|
conn->reply_fd = open(target, O_RDONLY | O_NONBLOCK);
|
||||||
@ -1701,14 +1701,14 @@ static void process_get(struct connection *conn) {
|
|||||||
/* open() failed */
|
/* open() failed */
|
||||||
if (errno == EACCES)
|
if (errno == EACCES)
|
||||||
default_reply(conn, 403, "Forbidden",
|
default_reply(conn, 403, "Forbidden",
|
||||||
"You don't have permission to access (%s).", conn->uri);
|
"You don't have permission to access (%s).", conn->url);
|
||||||
else if (errno == ENOENT)
|
else if (errno == ENOENT)
|
||||||
default_reply(conn, 404, "Not Found",
|
default_reply(conn, 404, "Not Found",
|
||||||
"The URI you requested (%s) was not found.", conn->uri);
|
"The URL you requested (%s) was not found.", conn->url);
|
||||||
else
|
else
|
||||||
default_reply(conn, 500, "Internal Server Error",
|
default_reply(conn, 500, "Internal Server Error",
|
||||||
"The URI you requested (%s) cannot be returned: %s.",
|
"The URL you requested (%s) cannot be returned: %s.",
|
||||||
conn->uri, strerror(errno));
|
conn->url, strerror(errno));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1722,7 +1722,7 @@ static void process_get(struct connection *conn) {
|
|||||||
|
|
||||||
/* make sure it's a regular file */
|
/* make sure it's a regular file */
|
||||||
if (S_ISDIR(filestat.st_mode)) {
|
if (S_ISDIR(filestat.st_mode)) {
|
||||||
redirect(conn, "%s/", conn->uri);
|
redirect(conn, "%s/", conn->url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!S_ISREG(filestat.st_mode)) {
|
else if (!S_ISREG(filestat.st_mode)) {
|
||||||
|
@ -63,7 +63,7 @@ class TestCases(unittest.TestCase):
|
|||||||
self.assertContains(body,
|
self.assertContains(body,
|
||||||
"<title>400 Bad Request</title>",
|
"<title>400 Bad Request</title>",
|
||||||
"<h1>Bad Request</h1>\n",
|
"<h1>Bad Request</h1>\n",
|
||||||
"You requested an invalid URI: %s\n"%path,
|
"You requested an invalid URL: %s\n"%path,
|
||||||
'Generated by darkhttpd')
|
'Generated by darkhttpd')
|
||||||
|
|
||||||
def nerf(s):
|
def nerf(s):
|
||||||
|
@ -6,7 +6,7 @@ static void
|
|||||||
test(const char *input, const char *expected)
|
test(const char *input, const char *expected)
|
||||||
{
|
{
|
||||||
char *tmp = xstrdup(input);
|
char *tmp = xstrdup(input);
|
||||||
char *out = make_safe_uri(tmp);
|
char *out = make_safe_url(tmp);
|
||||||
|
|
||||||
if (expected == NULL) {
|
if (expected == NULL) {
|
||||||
if (out == NULL)
|
if (out == NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user