--- a/src/httpsock.cc
+++ b/src/httpsock.cc
@@ -20,12 +20,19 @@
 #include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+       #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 
+#ifdef HAVE_SENDFILE
+#include <netinet/tcp.h>
+#include <sys/sendfile.h>
+#endif
+
 #include "config.hh"
 #include "socket.hh"
 #include "httpsock.hh"
@@ -36,6 +43,8 @@
 #define NOT_FOUND 2
 #define NOT_MOD 3
 
+extern char ROOT_DIR[];
+
 char *dayName[] = {
 	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 };
@@ -52,10 +61,10 @@
 
 AssocType assocNames[] =
 {
-	{ ".mp2", "audio/x-mpeg" },
-	{ ".mpa", "audio/x-mpeg" },
-	{ ".abs", "audio/x-mpeg" },
-	{ ".mpega", "audio/x-mpeg" },
+	{ ".mp2", "audio/mpeg" },
+	{ ".mpa", "audio/mpeg" },
+	{ ".abs", "audio/mpeg" },
+	{ ".mpega", "audio/mpeg" },
 	{ ".mpeg", "video/mpeg" },
 	{ ".mpg", "video/mpeg" },
 	{ ".mpe", "video/mpeg" },
@@ -65,14 +74,15 @@
 	{ ".bin", "application/octet-stream" },
 	{ ".com", "application/octet-stream" },
 	{ ".dll", "application/octet-stream" },
-	{ ".bmp", "image/x-MS-bmp" },
+	{ ".bmp", "image/bitmap" },
 	{ ".exe", "application/octet-stream" },
-	{ ".mid", "audio/x-midi" },
-	{ ".midi", "audio/x-midi" },
+	{ ".mid", "audio/midi" },
+	{ ".midi", "audio/midi" },
 	{ ".htm", "text/html" },
 	{ ".html", "text/html" },
 	{ ".txt", "text/plain" },
 	{ ".gif", "image/gif" },
+	{ ".css", "text/css" },
 	{ ".tar", "application/x-tar" },
 	{ ".jpg", "image/jpeg" },
 	{ ".jpeg", "image/jpeg" },
@@ -82,8 +92,13 @@
 	{ ".sys", "application/octet-stream" },
 	{ ".wav", "audio/x-wav" },
 	{ ".xbm", "image/x-xbitmap" },
-	{ ".zip", "application/x-zip" },
+	{ ".zip", "application/zip" },
 	{ ".deb", "application/x-debian-package" },
+	{ ".ps", "application/postscript" },
+	{ ".pdf", "application/pdf" },
+	{ ".xml", "text/xml" },
+	{ ".xml", "text/xml" },
+	{ ".swf", "application/x-shockwave-flash" },
 	{ NULL, NULL }
 };
 
@@ -161,22 +176,22 @@
 	return 0;
 }
 
-void error( FILE *out, int num, char *stat, char *msg, char *str )
+void error( FILE *out, int num, char *status, char *msg, char *str )
 {
 	FILE *in;
 	int numch;
-	char file[ 1200 ];
+	char *file;
 	char buf[ 1024 ];
 	struct stat fs;
 
-	fprintf( out, "HTTP/1.0 %s\r\n", stat );
+	fprintf( out, "HTTP/1.0 %s\r\n", status );
 	fprintf( out, "Date: %s\n", curTime() );
 	fprintf( out, "Server: %s\r\n", DHTTPDVERSION );
-//	fprintf( out, "MIME-version: 1.0\r\n" );
 	fprintf( out, "Content-type: text/html\r\n" );
 	fprintf( out, "\r\n" );
 
-	sprintf( file, "%s/..ERROR%i.html", WEBDIRPREFIX, num );
+	asprintf( &file, "%s/..ERROR%i.html", ROOT_DIR, num );
+
 	in = fopen( file, "r" );
 	if( in!=NULL )
 	{
@@ -192,6 +207,7 @@
 			while( numch );
 
 			fclose( in );
+			free(file);
 			return;
 		}
 		fclose( in );
@@ -200,6 +216,7 @@
 	fprintf( out, "<html><head><title>%s: Error %s</title></head>", DHTTPDVERSION, msg );
 	fprintf( out, "<h1>%s</h1><hr>", msg );
 	fprintf( out, "%s <em>Sorry!</em></body></html>", str );
+	free(file);
 }
 
 void screwed( FILE *out )
@@ -321,13 +338,38 @@
 	return 1;
 }
 
-int sendFile( FILE *out, char *name, char *modTime )
+void sendNotMod( FILE *out )
+{
+	fprintf( out, "HTTP/1.0 304 Not modified\r\n" );
+	fprintf( out, "Date: %s\r\n",curTime() );
+	fprintf( out, "Server: %s\r\n", DHTTPDVERSION );
+	fprintf( out, "\r\n" );
+}
+
+void sendHead( FILE *out, char *name, time_t tmMod, long filesize )
+{
+	fprintf( out, "HTTP/1.0 200 OK\r\n" );
+	fprintf( out, "Date: %s\n", curTime() );
+	fprintf( out, "Server: %s\r\n", DHTTPDVERSION );
+	fprintf( out, "Content-type: %s\r\n", guessType( name ) );
+	fprintf( out, "Last-modified: %s\r\n", getMimeTime( gmtime( &tmMod ) ) );
+	fprintf( out, "Content-length: %ld\r\n", filesize );
+	fprintf( out, "\r\n" );
+}
+
+int sendFile( FILE *out, char *name, char *modTime, bool simple, bool headOnly )
 {
 	FILE *in;
 	struct stat fs;
 	tm *tmMod;
+#ifdef HAVE_SENDFILE
+	off_t offset = 0;
+	struct stat st;
+	int cork=1;
+#else
 	char buf[ 1024 ];
-	int num;
+	int num = 0;
+#endif
 
 	if( badFileName( name ) )
 	{
@@ -354,58 +396,99 @@
 	
 	tmMod = gmtime( &fs.st_mtime );
 	
-	if( modTime!=NULL && useCache( tmMod, modTime ) )
+	/* HTTP ver 0.9 (simple) does not support if-modified-since */
+	if( !simple && modTime!=NULL && useCache( tmMod, modTime ) )
 	{
 		fclose( in );
-		fprintf( out, "HTTP/1.0 304 Not modified\r\n" );
-		fprintf( out, "Date: %s\r\n",curTime() );
-		fprintf( out, "Server: %s\r\n", DHTTPDVERSION );
-//		fprintf( out, "MIME-version: 1.0\r\n" );
-		fprintf( out, "\r\n" );
+		sendNotMod( out );
 		return OK;
 	}
 	
-	fprintf( out, "HTTP/1.0 200 OK\r\n" );
-	fprintf( out, "Date: %s\n", curTime() );
-	fprintf( out, "Server: %s\r\n", DHTTPDVERSION );
-//	fprintf( out, "MIME-version: 1.0\r\n" );
-	fprintf( out, "Content-type: %s\r\n", guessType( name ) );
-	fprintf( out, "Last-modified: %s\r\n", getMimeTime( tmMod ) );
-	fprintf( out, "Content-length: %i\r\n", fs.st_size );
-	fprintf( out, "\r\n" );
-
-	do
-	{
-		num = fread( buf, 1, 1024, in );
-		fwrite( buf, 1, num, out );
-	}
-	while( num );
-	
+#ifdef HAVE_SENDFILE
+	        setsockopt(fileno(out),SOL_TCP,TCP_CORK,&cork,sizeof(cork));
+#endif
+	/* HTTP ver 0.9 (simple) does not expect any headers */
+	if ( !simple )
+	{
+       	        sendHead( out, name, fs.st_mtime, fs.st_size );
+	}
+	fflush(out);
+	if ( !headOnly )
+	{
+#ifdef HAVE_SENDFILE
+		fstat(fileno(in),&st);
+		fflush(out);
+		sendfile(fileno(out),fileno(in),&offset,st.st_size);
+		cork=0;
+		setsockopt(fileno(out),SOL_TCP,TCP_CORK,&cork,sizeof(cork));
+#else
+		do
+		{
+			num = fread( buf, 1, 1024, in );
+			fwrite( buf, 1, num, out );
+		}
+		while( num );
+#endif
+        }
 	fclose( in );
 	
 	return OK;
 }
 
+static char * decodeURI (const char *uri)
+{
+  char *b, *buffer;
+  buffer = b = static_cast<char *>(malloc (strlen (uri) + 1));
+
+#define ASCII_TO_XDIGIT(c) (((c) >= '0' && (c) <= '9') \
+  ? ((c) - '0') \
+  : (tolower ((c)) - 'a' + 0x0a))
+
+  if (buffer) {
+    while (*uri) {
+      if (*uri == '%' && isxdigit (uri[1]) && isxdigit (uri[2])) {
+        *b++ = (ASCII_TO_XDIGIT (uri[1]) << 4) | ASCII_TO_XDIGIT (uri[2]);
+        uri += 3;
+      } else
+        *b++ = *uri++;
+    }
+
+    *b = '\0';
+
+    return buffer;
+  }
+
+  return NULL;
+}
+
 void HttpSocket::handle()
 {
 	char line[ 1024 ];
 	char cmd[ 1024 ];
 	char file[ 1200 ];
 	char ver[ 1024 ];
-	char file2[ 1200 ];
 	char ifmod[ 1024 ];
 	char *modTime;
 	char *str;
 	
-	int num;
+	int numTokens;
 	int status;
 	char *pos;
+	bool simple, headOnly;
 
 	str = fgets( line, 1024, io );
-	num = sscanf( line, "%s %s %s", cmd, file, ver );
-
-	strcpy( ifmod, "" );
+	numTokens = sscanf( line, "%s %s %s", cmd, file, ver );
+       simple = (numTokens == 2);
+	headOnly = !strcmp( cmd, "HEAD" );
+	if( ( strcmp( cmd, "GET" ) && !headOnly ) || ( numTokens < 2 ) )
+	{
+		screwed( io );
+		return;
+	}
+	ifmod[0]='\0';
 
+	/* HTTP/0.9 (simple) requests don't send headers */
+	if ( !simple ) {
 	do
 	{
 		str = fgets( line, 1024, io );
@@ -426,35 +509,33 @@
 		}
 	}
 	while( str!=NULL && strcmp( line, "\r\n" ) && strcmp( line, "\n" ) );
+	}
 
 	/* This is necessary for some stupid *
          * operating system such as SunOS    */
 	fflush( io );
 
-	modTime = strcmp( ifmod, "" ) ? ifmod : (char*) NULL;
-	
-	if( !strcmp( cmd, "GET" ) )
-	{
-		sprintf( file2, "%s%s%s", WEBDIRPREFIX, file[ 0 ]=='/' ? "" : "/", file );
-		status = sendFile( io, file2, modTime );
-		if( status )
-		{
-			if( !strcmp( file, "/" ) )
-			{
-				sprintf( file2, "%s/index.html", WEBDIRPREFIX );
-				if( sendFile( io, file2, modTime ) )
-				{
-					sendError( io, status );
-				}
-			}
-			else
-			{
-				sendError( io, status );
-			}
-		}
-	}
-	else
+ 	modTime = strcmp( ifmod, "" ) ? ifmod : (char*) NULL;
+
+        char *decodedfile = decodeURI (file);
+	char *file2;
+	asprintf( &file2, "%s%s%s%s"
+		  ,ROOT_DIR
+		  ,file[ 0 ]=='/' ? "" : "/"
+		  ,decodedfile ? decodedfile : file
+		  ,((file[0]=='\0') || (file[strlen(file)-1]=='/'))?
+		  "index.html"
+		  :
+		  ""
+		  );
+
+	status = sendFile( io, file2, modTime, simple, headOnly );
+	free(file2);
+        if (decodedfile) free (decodedfile);
+
+	if( status )
 	{
-		screwed( io );
+	    sendError( io, status );
 	}
+
 }
