Index: trunk/Common/dir.c
===================================================================
--- trunk/Common/dir.c	(revision 21)
+++ trunk/Common/dir.c	(revision 22)
@@ -10,5 +10,5 @@
 #include <string.h>
 
-int cm_sort(const void* _a, const void* _b){
+int cm_sort(const void* _a, const void* _b) {
 	char* a = *(char**)_a;
 	char* b = *(char**)_b;
@@ -16,12 +16,12 @@
 }
 
-char** cm_scandir(const char* path){
+char** cm_scandir(const char* path) {
 	DIR* dir = opendir(path);
-	if(dir != NULL){
+	if(dir != NULL) {
 		char** r = malloc(sizeof(*r));
 		r[0] = NULL;
 		struct dirent* d;
-		while((d = readdir(dir)) != NULL){
-			if(strcmp(d->d_name, ".") != 0){
+		while((d = readdir(dir)) != NULL) {
+			if(strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
 				struct stat s;
 				char* p = cm_strcat3(path, "/", d->d_name);
@@ -31,5 +31,6 @@
 				char** old = r;
 				int i;
-				for(i = 0; old[i] != NULL; i++);
+				for(i = 0; old[i] != NULL; i++)
+					;
 				r = malloc(sizeof(*r) * (i + 2));
 				for(i = 0; old[i] != NULL; i++) r[i] = old[i];
@@ -40,8 +41,20 @@
 		}
 		int len;
-		for(len = 0; r[len] != NULL; len++);
+		for(len = 0; r[len] != NULL; len++)
+			;
 		qsort(r, len, sizeof(char*), cm_sort);
+
+		char** old = r;
+		int i;
+		for(i = 0; old[i] != NULL; i++)
+			;
+		r = malloc(sizeof(*r) * (i + 2));
+		for(i = 0; old[i] != NULL; i++) r[i + 1] = old[i];
+		r[0] = cm_strdup("../");
+		r[i + 1] = NULL;
+		free(old);
+
 		return r;
-	}else{
+	} else {
 		return NULL;
 	}
Index: trunk/Server/config.c
===================================================================
--- trunk/Server/config.c	(revision 21)
+++ trunk/Server/config.c	(revision 22)
@@ -31,5 +31,5 @@
 }
 
-bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost){
+bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost) {
 	int i;
 	bool found = false;
@@ -37,12 +37,12 @@
 	bool perm = false;
 again:
-	for(i = 0; i < vhost->dir_count; i++){
+	for(i = 0; i < vhost->dir_count; i++) {
 		struct tw_dir_entry* e = &vhost->dirs[i];
 		pathstart = false;
-		if(strlen(path) >= strlen(e->dir)){
+		if(strlen(path) >= strlen(e->dir)) {
 			pathstart = true;
 			int j;
-			for(j = 0; path[j] != 0 && e->dir[j] != 0; j++){
-				if(path[j] != e->dir[j]){
+			for(j = 0; path[j] != 0 && e->dir[j] != 0; j++) {
+				if(path[j] != e->dir[j]) {
 					pathstart = false;
 					break;
@@ -52,7 +52,7 @@
 		char* noslash = cm_strdup(e->dir);
 		noslash[strlen(noslash) - 1] = 0;
-		if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart){
+		if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart) {
 			found = true;
-			if(strcmp(e->name, "all") == 0){
+			if(strcmp(e->name, "all") == 0) {
 				perm = e->type == TW_DIR_ALLOW;
 			}
@@ -60,5 +60,5 @@
 		free(noslash);
 	}
-	if(!found && vhost != &config.root){
+	if(!found && vhost != &config.root) {
 		vhost = &config.root;
 		goto again;
@@ -82,4 +82,5 @@
 	config.root.mime_count = 0;
 	config.root.dir_count = 0;
+	config.root.icon_count = 0;
 	config.vhost_count = 0;
 	config.module_count = 0;
@@ -180,4 +181,5 @@
 								current->dir_count = 0;
 								current->mime_count = 0;
+								current->icon_count = 0;
 								int i;
 								current->name = cm_strdup(vhost);
@@ -247,5 +249,5 @@
 							cm_log("Config", "Missing extension at line %d", ln);
 							stop = 1;
-						}else if(r[2] == NULL) {
+						} else if(r[2] == NULL) {
 							cm_log("Config", "Missing MIME at line %d", ln);
 							stop = 1;
@@ -254,4 +256,16 @@
 							e->ext = cm_strdup(r[1]);
 							e->mime = cm_strdup(r[2]);
+						}
+					} else if(cm_strcaseequ(r[0], "Icon")) {
+						if(r[1] == NULL) {
+							cm_log("Config", "Missing MIME at line %d", ln);
+							stop = 1;
+						} else if(r[2] == NULL) {
+							cm_log("Config", "Missing path at line %d", ln);
+							stop = 1;
+						} else {
+							struct tw_icon_entry* e = &current->icons[current->icon_count++];
+							e->mime = cm_strdup(r[1]);
+							e->icon = cm_strdup(r[2]);
 						}
 					} else if(cm_strcaseequ(r[0], "LoadModule")) {
Index: trunk/Server/http.c
===================================================================
--- trunk/Server/http.c	(revision 21)
+++ trunk/Server/http.c	(revision 22)
@@ -60,6 +60,12 @@
 		tv.tv_sec = 5;
 		tv.tv_usec = 0;
-		int n = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
-		if(n == 0) break;
+		if(!SSL_has_pending(ssl)) {
+			int n = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
+			if(n <= 0) {
+				free(header);
+				tw_free_request(req);
+				return -1;
+			}
+		}
 		int len = tw_read(ssl, sock, buffer, 512);
 		if(len <= 0) break;
Index: trunk/Server/server.c
===================================================================
--- trunk/Server/server.c	(revision 21)
+++ trunk/Server/server.c	(revision 22)
@@ -166,9 +166,9 @@
 	size_t incr = 0;
 	while(1) {
-		if(f != NULL){
+		if(f != NULL) {
 			char buffer[128];
 			fread(buffer, size < 128 ? size : 128, 1, f);
 			tw_write(ssl, sock, buffer, size < 128 ? size : 128);
-		}else{
+		} else {
 			tw_write(ssl, sock, (unsigned char*)doc + incr, size < 128 ? size : 128);
 		}
@@ -269,4 +269,46 @@
 }
 
+char* tw_get_mime(const char* ext, struct tw_config_entry* vhost_entry) {
+	char* mime = "application/octet-stream";
+	if(ext == NULL) return mime;
+	bool set = false;
+	int i;
+	for(i = 0; i < vhost_entry->mime_count; i++) {
+		if(strcmp(vhost_entry->mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(vhost_entry->mimes[i].ext, ext) == 0)) {
+			mime = vhost_entry->mimes[i].mime;
+			set = true;
+		}
+	}
+	if(!set) {
+		for(i = 0; i < config.root.mime_count; i++) {
+			if(strcmp(config.root.mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(config.root.mimes[i].ext, ext) == 0)) {
+				mime = config.root.mimes[i].mime;
+			}
+		}
+	}
+	return mime;
+}
+
+char* tw_get_icon(const char* mime, struct tw_config_entry* vhost_entry) {
+	char* icon = "";
+	if(mime == NULL) return "";
+	bool set = false;
+	int i;
+	for(i = 0; i < vhost_entry->icon_count; i++) {
+		if(strcmp(vhost_entry->icons[i].mime, "all") == 0 || (mime != NULL && strcmp(vhost_entry->icons[i].mime, mime) == 0)) {
+			icon = vhost_entry->icons[i].icon;
+			set = true;
+		}
+	}
+	if(!set) {
+		for(i = 0; i < config.root.icon_count; i++) {
+			if(strcmp(config.root.icons[i].mime, "all") == 0 || (mime != NULL && strcmp(config.root.icons[i].mime, mime) == 0)) {
+				icon = config.root.icons[i].icon;
+			}
+		}
+	}
+	return icon;
+}
+
 #ifdef __MINGW32__
 struct pass_entry {
@@ -307,6 +349,6 @@
 		char* vhost = cm_strdup(config.hostname);
 		int i;
-		for(i = 0; req.headers[i] != NULL; i += 2){
-			if(cm_strcaseequ(req.headers[i], "Host")){
+		for(i = 0; req.headers[i] != NULL; i += 2) {
+			if(cm_strcaseequ(req.headers[i], "Host")) {
 				free(vhost);
 				vhost = req.headers[i + 1];
@@ -317,6 +359,6 @@
 		int port = s == NULL ? 80 : 443;
 		char* host = cm_strdup(vhost);
-		for(i = 0; vhost[i] != 0; i++){
-			if(vhost[i] == ':'){
+		for(i = 0; vhost[i] != 0; i++) {
+			if(vhost[i] == ':') {
 				host[i] = 0;
 				port = atoi(host + i + 1);
@@ -347,8 +389,8 @@
 			cm_log("Server", "Filesystem path is %s", path);
 			struct stat st;
-			if(stat(path, &st) == 0){
-				if(!tw_permission_allowed(path, addr, req, vhost_entry)){
+			if(stat(path, &st) == 0) {
+				if(!tw_permission_allowed(path, addr, req, vhost_entry)) {
 					tw_http_error(s, sock, 403, name, port);
-				}else if(S_ISDIR(st.st_mode)){
+				} else if(S_ISDIR(st.st_mode)) {
 					char* str = malloc(1);
 					str[0] = 0;
@@ -368,10 +410,42 @@
 					addstring(&str, "				<th>Filename</th>\n");
 					addstring(&str, "			</tr>\n");
-					if(items != NULL){
-						for(i = 0; items[i] != NULL; i++){
+					if(items != NULL) {
+						for(i = 0; items[i] != NULL; i++) {
+							char* ext = NULL;
+							int j;
+							for(j = strlen(items[i]) - 1; j >= 0; j--) {
+								if(items[i][j] == '.') {
+									ext = cm_strdup(items[i] + j);
+									break;
+								}
+							}
+							char* mime = tw_get_mime(ext, vhost_entry);
+							if(strcmp(items[i], "../") == 0) {
+								mime = "misc/parent";
+							} else if(items[i][strlen(items[i]) - 1] == '/') {
+								mime = "misc/dir";
+							}
+							char* icon = tw_get_icon(mime, vhost_entry);
+							if(ext != NULL) free(ext);
+							char* itm = cm_strdup(items[i]);
+							if(strlen(itm) >= 32) {
+								if(itm[strlen(itm) - 1] == '/') {
+									itm[31] = 0;
+									itm[30] = '/';
+									itm[29] = '.';
+									itm[28] = '.';
+									itm[27] = '.';
+								} else {
+									itm[31] = 0;
+									itm[30] = '.';
+									itm[29] = '.';
+									itm[28] = '.';
+								}
+							}
 							addstring(&str, "<tr>\n");
-							addstring(&str, "	<td></td>\n");
-							addstring(&str, "	<td><a href=\"%l\">%h</a></td>\n", items[i], items[i]);
+							addstring(&str, "	<td><img src=\"%s\" alt=\"icon\"></td>\n", icon);
+							addstring(&str, "	<td><a href=\"%l\"><code>%h</code></a></td>\n", items[i], itm);
 							addstring(&str, "</tr>\n");
+							free(itm);
 						}
 					}
@@ -383,28 +457,13 @@
 					tw_process_page(s, sock, tw_http_status(200), "text/html", NULL, str, strlen(str));
 					free(str);
-				}else{
-					char* mime = "application/octet-stream";
-					bool set = false;
+				} else {
 					char* ext = NULL;
-					for(i = strlen(req.path) - 1; i >= 0; i--){
-						if(req.path[i] == '.'){
+					for(i = strlen(req.path) - 1; i >= 0; i--) {
+						if(req.path[i] == '.') {
 							ext = cm_strdup(req.path + i);
 							break;
 						}
 					}
-					for(i = 0; i < vhost_entry->mime_count; i++){
-						if(strcmp(vhost_entry->mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(vhost_entry->mimes[i].ext, ext) == 0)){
-							mime = vhost_entry->mimes[i].mime;
-							set = true;
-						}
-					}
-					if(!set){
-						for(i = 0; i < config.root.mime_count; i++){
-							if(strcmp(config.root.mimes[i].ext, "all") == 0 || (ext != NULL && strcmp(config.root.mimes[i].ext, ext) == 0)){
-								mime = config.root.mimes[i].mime;
-								set = true;
-							}
-						}
-					}
+					char* mime = tw_get_mime(ext, vhost_entry);
 					if(ext != NULL) free(ext);
 					FILE* f = fopen(path, "rb");
@@ -412,5 +471,5 @@
 					fclose(f);
 				}
-			}else{
+			} else {
 				tw_http_error(s, sock, 404, name, port);
 			}
@@ -419,4 +478,5 @@
 		free(vhost);
 		free(host);
+	} else if(ret == -1) {
 	} else {
 		tw_http_error(s, sock, 400, name, port);
Index: trunk/Server/tw_config.h
===================================================================
--- trunk/Server/tw_config.h	(revision 21)
+++ trunk/Server/tw_config.h	(revision 22)
@@ -22,9 +22,10 @@
 #endif
 
-#define MAX_PORTS	1024
-#define MAX_VHOSTS	1024
-#define MAX_MODULES	1024
-#define MAX_DIRS 	1024
-#define MAX_MIME 	1024
+#define MAX_PORTS 1024
+#define MAX_VHOSTS 1024
+#define MAX_MODULES 1024
+#define MAX_DIRS 1024
+#define MAX_MIME 1024
+#define MAX_ICON 1024
 
 enum TW_DIR_TYPE {
@@ -44,4 +45,9 @@
 };
 
+struct tw_icon_entry {
+	char* mime;
+	char* icon;
+};
+
 struct tw_config_entry {
 	char* name;
@@ -54,4 +60,6 @@
 	struct tw_mime_entry mimes[MAX_DIRS];
 	int mime_count;
+	struct tw_icon_entry icons[MAX_DIRS];
+	int icon_count;
 };
 
Index: trunk/example.conf
===================================================================
--- trunk/example.conf	(revision 21)
+++ trunk/example.conf	(revision 22)
@@ -12,6 +12,13 @@
 MIMEType all application/octet-stream
 MIMEType .html text/html
+MIMEType .txt text/plain
+MIMEType .png image/png
 
-DocumentRoot /
+Icon all /icons/unknown.png
+Icon text/plain /icons/text.png
+Icon misc/dir /icons/folder.png
+Icon misc/parent /icons/parent.png
+
+DocumentRoot /var/www
 
 BeginDirectory /
@@ -19,8 +26,4 @@
 EndDirectory
 
-BeginDirectory /var/www
-	Deny all
-EndDirectory
-
 BeginVirtualHost nishinbsd-ssd
 EndVirtualHost
