commit 5f715ce43fa60b2347d6dc64588c5ffe61ebc067 from: Omar Polo date: Tue Feb 02 09:48:32 2021 UTC print the header in the directory listing commit - 3c680bddab146e8c8ccf5eba1fec7e1ee978d638 commit + 5f715ce43fa60b2347d6dc64588c5ffe61ebc067 blob - a8f6f3d330e65c19d715ddf21218470499fb4e23 blob + c8149d526f57bcc39d29238aa9193c1734aafb79 --- ChangeLog +++ ChangeLog @@ -1,3 +1,7 @@ +2021-02-02 Omar Polo + + * server.c (handle_dirlist_head): print the header in the directory listing + 2021-02-01 Omar Polo * parse.y (servopt): require absolute paths in config file blob - 1ba4a9e90b1b681d79146270694f5d845b642855 blob + dba93c368806aeb65c3a42e175d87796950ae333 --- gmid.h +++ gmid.h @@ -131,12 +131,13 @@ typedef void (*statefn)(struct pollfd*, struct client* /* * DFA: handle_handshake is the initial state, close_conn the final. + * Sometimes we have an enter_* function to handle the state switch. * * handle_handshake -> handle_open_conn * handle_handshake -> close_conn // on err * * handle_open_conn -> handle_cgi_reply // via open_file/dir/... - * handle_open_conn -> send_directory_listing // ...same + * handle_open_conn -> handle_dirlist // ...same * handle_open_conn -> send_file // ...same * handle_open_conn -> start_reply // on error * @@ -144,6 +145,9 @@ typedef void (*statefn)(struct pollfd*, struct client* * handle_cgi_reply -> start_reply // on error * * handle_cgi -> close_conn + * + * handle_dirlist -> send_directory_listing + * handle_dirlist -> close_conn // on error * * send_directory_listing -> close_conn * @@ -229,6 +233,8 @@ void start_cgi(const char*, const char*, struct poll void send_file(struct pollfd*, struct client*); void open_dir(struct pollfd*, struct client*); void redirect_canonical_dir(struct pollfd*, struct client*); +void enter_handle_dirlist(struct pollfd*, struct client*); +void handle_dirlist(struct pollfd*, struct client*); int read_next_dir_entry(struct client*); void send_directory_listing(struct pollfd*, struct client*); void cgi_poll_on_child(struct pollfd*, struct client*); blob - 5ffd83fbb081331521f87cd015054fe9521eb30d blob + 6de3e30c26b75b35788d4f649a6a93d7b63ac3ea --- regress/runtime +++ regress/runtime @@ -215,7 +215,7 @@ echo OK GET / with auto index eq "$(head /dir)" "30 /dir/" "Unexpected head for /dir" eq "$(head /dir/)" "20 text/gemini" "Unexpected head for /dir/" -eq "$(get /dir/|wc -l|xargs)" "3" "Unexpected body for /dir/" +eq "$(get /dir/|wc -l|xargs)" "5" "Unexpected body for /dir/" echo OK GET /dir/ with auto index on check "should be running" blob - 9292e0c3b60a1ba10fc9c0ef463d9c3cb4c955fc blob + d1b3a1079a053524226aee0e0a8b96638bcb13bf --- server.c +++ server.c @@ -543,7 +543,7 @@ open_dir(struct pollfd *fds, struct client *c) } c->fd = dirfd; - c->next = send_directory_listing; + c->next = enter_handle_dirlist; if ((c->dir = fdopendir(c->fd)) == NULL) { LOGE(c, "can't fdopendir(%d) (vhost:%s) %s: %s", @@ -580,7 +580,56 @@ redirect_canonical_dir(struct pollfd *fds, struct clie start_reply(fds, c, TEMP_REDIRECT, c->sbuf); } + +void +enter_handle_dirlist(struct pollfd *fds, struct client *c) +{ + char b[PATH_MAX]; + size_t l; + strlcpy(b, c->iri.path, sizeof(b)); + l = snprintf(c->sbuf, sizeof(c->sbuf), + "# Index of %s\n\n", b); + if (l >= sizeof(c->sbuf)) { + /* this is impossible, given that we have enough space + * in c->sbuf to hold the ancilliary string plus the + * full path; but it wouldn't read nice without some + * error checking, and I'd like to avoid a strlen. */ + close_conn(fds, c); + return; + } + c->len = l; + + c->state = handle_dirlist; + handle_dirlist(fds, c); +} + +void +handle_dirlist(struct pollfd *fds, struct client *c) +{ + ssize_t r; + + while (c->len > 0) { + switch (r = tls_write(c->ctx, c->sbuf + c->off, c->len)) { + case -1: + close_conn(fds, c); + return; + case TLS_WANT_POLLOUT: + fds->events = POLLOUT; + return; + case TLS_WANT_POLLIN: + fds->events = POLLIN; + return; + default: + c->off += r; + c->len -= r; + } + } + + c->state = send_directory_listing; + send_directory_listing(fds, c); +} + int read_next_dir_entry(struct client *c) {