From e74bb5a077aeb98c4c2c4d6628ebd029ef6e610a Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Mon, 24 Nov 2003 11:44:22 +0000 Subject: [PATCH] . Added redirect(). . Moved 404 reply up to stat() section. . Redirect /dir to /dir/ . Separate permissions (403 Forbidden) from other fopen() failures (500 Internal Server Error) --- trunk/darkhttpd.c | 72 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/trunk/darkhttpd.c b/trunk/darkhttpd.c index b758ccb..9174d5e 100644 --- a/trunk/darkhttpd.c +++ b/trunk/darkhttpd.c @@ -1221,6 +1221,48 @@ static void default_reply(struct connection *conn, +/* --------------------------------------------------------------------------- + * Redirection. + */ +static void redirect(struct connection *conn, const char *format, ...) +{ + char *where, date[DATE_LEN]; + va_list va; + + va_start(va, format); + xvasprintf(&where, format, va); + va_end(va); + + /* Only really need to calculate the date once. */ + (void)rfc1123_date(date, time(NULL)); + + conn->reply_length = xasprintf(&(conn->reply), + "301 Moved Permanently\n" + "

Moved Permanently

\n" + "Moved to: %s\n" /* where x 2 */ + "
\n" + "Generated by %s on %s\n" + "\n", + where, where, pkgname, date); + + conn->header_length = xasprintf(&(conn->header), + "HTTP/1.1 301 Moved Permanently\r\n" + "Date: %s\r\n" + "Server: %s\r\n" + "Location: %s\r\n" + "%s" /* keep-alive */ + "Content-Length: %d\r\n" + "Content-Type: text/html\r\n" + "\r\n", + date, pkgname, where, keep_alive(conn), conn->reply_length); + + free(where); + conn->reply_type = REPLY_GENERATED; + conn->http_code = 301; +} + + + /* --------------------------------------------------------------------------- * Parses a single HTTP request field. Returns string from end of [field] to * first \r, \n or end of request string. Returns NULL if [field] can't be @@ -1426,14 +1468,23 @@ static void process_get(struct connection *conn) */ if (stat(target, &filestat) == -1) { - default_reply(conn, 500, "Internal Server Error", - "stat() failed: %s.", strerror(errno)); + if (errno == ENOENT) + default_reply(conn, 404, "Not Found", + "The URI you requested (%s) was not found.", conn->uri); + else + default_reply(conn, 500, "Internal Server Error", + "stat(%s) failed: %s.", conn->uri, strerror(errno)); + return; } /* make sure it's a regular file */ - if (!S_ISREG(filestat.st_mode)) - /*(filestat.st_mode & S_IFMT) != S_IFREG)*/ + if (S_ISDIR(filestat.st_mode)) + { + redirect(conn, "%s/", conn->uri); + return; + } + else if (!S_ISREG(filestat.st_mode)) { default_reply(conn, 403, "Forbidden", "Not a regular file."); return; @@ -1445,19 +1496,18 @@ static void process_get(struct connection *conn) if (conn->reply_file == NULL) { /* fopen() failed */ - if (errno == ENOENT) - default_reply(conn, 404, "Not Found", - "The URI you requested (%s) was not found.", conn->uri); - else + if (errno == EACCES) default_reply(conn, 403, "Forbidden", - "The URI you requested (%s) cannot be returned.
\n" - "%s.", /* reason why */ + "You don't have permission to access (%s).", conn->uri); + else + default_reply(conn, 500, "Internal Server Error", + "The URI you requested (%s) cannot be returned: %s.", conn->uri, strerror(errno)); return; } - /* get information on the file */ + /* get information on the file, again, just in case */ if (fstat(fileno(conn->reply_file), &filestat) == -1) { default_reply(conn, 500, "Internal Server Error",