mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
. Implemented apbuf API.
. Reworked generate_dir_listing() to use apbuf - much nicer now.
This commit is contained in:
parent
2776f8c35e
commit
3e378caaf0
@ -355,6 +355,69 @@ static unsigned int xasprintf(char **ret, const char *format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
* Append buffer code. A somewhat efficient string buffer with pool-based
|
||||||
|
* reallocation.
|
||||||
|
*/
|
||||||
|
#define APBUF_INIT 4096
|
||||||
|
#define APBUF_GROW APBUF_INIT
|
||||||
|
struct apbuf
|
||||||
|
{
|
||||||
|
size_t length, pool;
|
||||||
|
char *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static struct apbuf *make_apbuf(void)
|
||||||
|
{
|
||||||
|
struct apbuf *buf = xmalloc(sizeof(struct apbuf));
|
||||||
|
buf->length = 0;
|
||||||
|
buf->pool = APBUF_INIT;
|
||||||
|
buf->str = xmalloc(buf->pool);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void appendl(struct apbuf *buf, const char *s, const size_t len)
|
||||||
|
{
|
||||||
|
if (buf->pool <= buf->length + len)
|
||||||
|
{
|
||||||
|
/* pool has dried up */
|
||||||
|
while (buf->pool <= buf->length + len) buf->pool += APBUF_GROW;
|
||||||
|
buf->str = xrealloc(buf->str, buf->pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf->str + buf->length, s, len+1);
|
||||||
|
buf->length += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void append(struct apbuf *buf, const char *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
appendl(buf, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void appendf(struct apbuf *buf, const char *format, ...)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
va_list va;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
len = xvasprintf(&tmp, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
appendl(buf, tmp, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
* Make the specified socket non-blocking.
|
* Make the specified socket non-blocking.
|
||||||
*/
|
*/
|
||||||
@ -1498,6 +1561,7 @@ static ssize_t make_sorted_dirlist(const char *path, struct dlent ***output)
|
|||||||
qsort(list, entries, sizeof(struct dlent*), dlent_cmp);
|
qsort(list, entries, sizeof(struct dlent*), dlent_cmp);
|
||||||
*output = xrealloc(list, sizeof(struct dlent*) * entries);
|
*output = xrealloc(list, sizeof(struct dlent*) * entries);
|
||||||
return entries;
|
return entries;
|
||||||
|
#undef POOL_INCR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1520,57 +1584,66 @@ static void cleanup_sorted_dirlist(struct dlent **list, const ssize_t size)
|
|||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
* Generate directory listing.
|
* Generate directory listing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* FIXME: this is awful: */
|
|
||||||
#define appendf(dest, format...) do { char *tmp1, *tmp2; \
|
|
||||||
xasprintf(&tmp1, format); xasprintf(&tmp2, "%s%s", dest, tmp1); \
|
|
||||||
safefree(dest); dest=tmp2; safefree(tmp1); } while(0)
|
|
||||||
static void generate_dir_listing(struct connection *conn, const char *path)
|
static void generate_dir_listing(struct connection *conn, const char *path)
|
||||||
{
|
{
|
||||||
char *listing, date[DATE_LEN];
|
char date[DATE_LEN];
|
||||||
struct dlent **list;
|
struct dlent **list;
|
||||||
ssize_t listsize;
|
ssize_t listsize;
|
||||||
size_t maxlen = 0;
|
size_t maxlen = 0;
|
||||||
int i;
|
int i;
|
||||||
|
struct apbuf *listing = make_apbuf();
|
||||||
|
|
||||||
listsize = make_sorted_dirlist(path, &list); /* FIXME return -1 */
|
listsize = make_sorted_dirlist(path, &list);
|
||||||
|
if (listsize == -1)
|
||||||
|
{
|
||||||
|
default_reply(conn, 500, "Internal Server Error",
|
||||||
|
"Couldn't list directory: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
xasprintf(&listing, "<tt><pre>\n");
|
|
||||||
for (i=0; i<listsize; i++)
|
for (i=0; i<listsize; i++)
|
||||||
{
|
{
|
||||||
size_t tmp = strlen(list[i]->name);
|
size_t tmp = strlen(list[i]->name);
|
||||||
if (maxlen < tmp) maxlen = tmp;
|
if (maxlen < tmp) maxlen = tmp;
|
||||||
}
|
}
|
||||||
maxlen++;
|
|
||||||
|
appendf(listing,
|
||||||
|
"<html><head><title>%s</title></head><body>\n"
|
||||||
|
"<h1>%s</h1>\n"
|
||||||
|
"<tt><pre>\n",
|
||||||
|
conn->uri, conn->uri);
|
||||||
|
|
||||||
for (i=0; i<listsize; i++)
|
for (i=0; i<listsize; i++)
|
||||||
{
|
{
|
||||||
int j;
|
|
||||||
appendf(listing, "<a href=\"%s\">%s</a>",
|
appendf(listing, "<a href=\"%s\">%s</a>",
|
||||||
list[i]->name, list[i]->name);
|
list[i]->name, list[i]->name);
|
||||||
if (list[i]->is_dir) appendf(listing, "/");
|
|
||||||
|
if (list[i]->is_dir)
|
||||||
|
append(listing, "/\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int j;
|
||||||
for (j=strlen(list[i]->name); j<maxlen; j++)
|
for (j=strlen(list[i]->name); j<maxlen; j++)
|
||||||
appendf(listing, " ");
|
append(listing, " ");
|
||||||
if (!list[i]->is_dir) appendf(listing, "%10d\n", list[i]->size);
|
|
||||||
appendf(listing, "\n");
|
appendf(listing, "%10d\n", list[i]->size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_sorted_dirlist(list, listsize);
|
cleanup_sorted_dirlist(list, listsize);
|
||||||
safefree(list);
|
safefree(list);
|
||||||
appendf(listing, "</pre></tt>\n");
|
|
||||||
|
|
||||||
/* Only really need to calculate the date once. */
|
|
||||||
(void)rfc1123_date(date, time(NULL));
|
(void)rfc1123_date(date, time(NULL));
|
||||||
|
appendf(listing,
|
||||||
conn->reply_length = xasprintf(&(conn->reply),
|
"</pre></tt>\n"
|
||||||
"<html><head><title>%s</title></head><body>\n"
|
|
||||||
"<h1>%s</h1>\n"
|
|
||||||
"%s\n"
|
|
||||||
"<hr>\n"
|
"<hr>\n"
|
||||||
"Generated by %s on %s\n"
|
"Generated by %s on %s\n"
|
||||||
"</body></html>\n",
|
"</body></html>\n",
|
||||||
conn->uri, conn->uri, listing, pkgname, date);
|
pkgname, date);
|
||||||
safefree(listing);
|
|
||||||
|
conn->reply = listing->str;
|
||||||
|
conn->reply_length = listing->length;
|
||||||
|
safefree(listing); /* don't free inside of listing */
|
||||||
|
|
||||||
conn->header_length = xasprintf(&(conn->header),
|
conn->header_length = xasprintf(&(conn->header),
|
||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user