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",