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.
|
||||
*/
|
||||
@ -1498,6 +1561,7 @@ static ssize_t make_sorted_dirlist(const char *path, struct dlent ***output)
|
||||
qsort(list, entries, sizeof(struct dlent*), dlent_cmp);
|
||||
*output = xrealloc(list, sizeof(struct dlent*) * 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.
|
||||
*/
|
||||
|
||||
/* 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)
|
||||
{
|
||||
char *listing, date[DATE_LEN];
|
||||
char date[DATE_LEN];
|
||||
struct dlent **list;
|
||||
ssize_t listsize;
|
||||
size_t maxlen = 0;
|
||||
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++)
|
||||
{
|
||||
size_t tmp = strlen(list[i]->name);
|
||||
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++)
|
||||
{
|
||||
int j;
|
||||
appendf(listing, "<a href=\"%s\">%s</a>",
|
||||
list[i]->name, list[i]->name);
|
||||
if (list[i]->is_dir) appendf(listing, "/");
|
||||
for (j=strlen(list[i]->name); j<maxlen; j++)
|
||||
appendf(listing, " ");
|
||||
if (!list[i]->is_dir) appendf(listing, "%10d\n", list[i]->size);
|
||||
appendf(listing, "\n");
|
||||
|
||||
if (list[i]->is_dir)
|
||||
append(listing, "/\n");
|
||||
else
|
||||
{
|
||||
int j;
|
||||
for (j=strlen(list[i]->name); j<maxlen; j++)
|
||||
append(listing, " ");
|
||||
|
||||
appendf(listing, "%10d\n", list[i]->size);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup_sorted_dirlist(list, listsize);
|
||||
safefree(list);
|
||||
appendf(listing, "</pre></tt>\n");
|
||||
|
||||
/* Only really need to calculate the date once. */
|
||||
(void)rfc1123_date(date, time(NULL));
|
||||
|
||||
conn->reply_length = xasprintf(&(conn->reply),
|
||||
"<html><head><title>%s</title></head><body>\n"
|
||||
"<h1>%s</h1>\n"
|
||||
"%s\n"
|
||||
appendf(listing,
|
||||
"</pre></tt>\n"
|
||||
"<hr>\n"
|
||||
"Generated by %s on %s\n"
|
||||
"</body></html>\n",
|
||||
conn->uri, conn->uri, listing, pkgname, date);
|
||||
safefree(listing);
|
||||
pkgname, date);
|
||||
|
||||
conn->reply = listing->str;
|
||||
conn->reply_length = listing->length;
|
||||
safefree(listing); /* don't free inside of listing */
|
||||
|
||||
conn->header_length = xasprintf(&(conn->header),
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
|
Loading…
Reference in New Issue
Block a user