diff -Naur dillo-0.8.6.ori/src/IO/Makefile.am dillo-0.8.6/src/IO/Makefile.am
--- dillo-0.8.6.ori/src/IO/Makefile.am	2004-08-04 15:58:25.000000000 +0200
+++ dillo-0.8.6/src/IO/Makefile.am	2007-05-10 10:05:41.426732181 +0200
@@ -11,6 +11,7 @@
 	Url.h \
 	proto.c	\
 	http.c \
+	file.c \
 	dpi.c \
 	IO.c \
 	IO.h
diff -Naur dillo-0.8.6.ori/src/IO/Makefile.in dillo-0.8.6/src/IO/Makefile.in
--- dillo-0.8.6.ori/src/IO/Makefile.in	2006-04-26 18:07:22.000000000 +0200
+++ dillo-0.8.6/src/IO/Makefile.in	2007-05-10 10:05:41.428731876 +0200
@@ -54,7 +54,7 @@
 libDio_a_AR = $(AR) $(ARFLAGS)
 libDio_a_LIBADD =
 am_libDio_a_OBJECTS = mime.$(OBJEXT) about.$(OBJEXT) Url.$(OBJEXT) \
-	proto.$(OBJEXT) http.$(OBJEXT) dpi.$(OBJEXT) IO.$(OBJEXT)
+	proto.$(OBJEXT) http.$(OBJEXT) file.$(OBJEXT) dpi.$(OBJEXT) IO.$(OBJEXT)
 libDio_a_OBJECTS = $(am_libDio_a_OBJECTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -189,6 +189,7 @@
 	Url.h \
 	proto.c	\
 	http.c \
+	file.c \
 	dpi.c \
 	IO.c \
 	IO.h
@@ -245,6 +246,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/about.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpi.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mime.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto.Po@am__quote@
 
diff -Naur dillo-0.8.6.ori/src/IO/Url.c dillo-0.8.6/src/IO/Url.c
--- dillo-0.8.6.ori/src/IO/Url.c	2006-01-03 20:44:32.000000000 +0100
+++ dillo-0.8.6/src/IO/Url.c	2007-05-10 10:05:41.430731569 +0200
@@ -83,7 +83,7 @@
 ChainFunction_t a_Url_get_ccc_funct(const DilloUrl *Url)
 {
    static UrlMethod2_t cccList[] = { {"http" , a_Http_ccc},
-                                     {"file" , a_Dpi_ccc},
+                                     {"file" , a_File_ccc},
                                      {"about", a_About_ccc},
                                      {"dpi" , a_Dpi_ccc},
                                      {"ftp" , a_Dpi_ccc},
diff -Naur dillo-0.8.6.ori/src/IO/Url.h dillo-0.8.6/src/IO/Url.h
--- dillo-0.8.6.ori/src/IO/Url.h	2005-10-27 18:20:22.000000000 +0200
+++ dillo-0.8.6/src/IO/Url.h	2007-05-10 10:05:41.431731417 +0200
@@ -29,6 +29,8 @@
 
 void a_Http_ccc (int Op, int Branch, int Dir, ChainLink *Info,
                  void *Data1, void *Data2);
+void a_File_ccc(int Op, int Branch, int Dir, ChainLink *Info,
+                 void *Data1, void *Data2);
 void a_About_ccc(int Op, int Branch, int Dir, ChainLink *Info,
                  void *Data1, void *Data2);
 void a_IO_ccc   (int Op, int Branch, int Dir, ChainLink *Info,
diff -Naur dillo-0.8.6.ori/src/IO/file.c dillo-0.8.6/src/IO/file.c
--- dillo-0.8.6.ori/src/IO/file.c	1970-01-01 01:00:00.000000000 +0100
+++ dillo-0.8.6/src/IO/file.c	2007-05-10 10:05:41.434730960 +0200
@@ -0,0 +1,263 @@
+/*
+ * File: file.c
+ *
+ * Copyright (C) 1997 Raph Levien <raph@acm.org>
+ * Copyright (C) 1999, 2001 Jorge Arellano Cid <jcid@dillo.org>
+ * Copyright (C) 2007 Dario Rodriguez <dario@softhome.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <config.h>
+#include "IO.h"
+#include "Url.h"
+#include "../nav.h"
+#include "../web.h"
+#include "../msg.h"
+
+typedef struct _FileInfo FileInfo_t;
+
+struct _FileInfo {
+   gint FD_Read;
+   gint FD_Write;
+};
+
+
+/*
+ * Header text for page
+ */
+static char Header_Generic1[]=
+"Content-Type: ";
+static char Header_Generic2[]=
+"\n\n";
+
+static struct {
+	int Off;
+	int Len;
+	char *Data;
+	char Dont_Care;
+	char *mime;
+} File_Magic[]={
+	{0,8,"\x89PNG\x0d\x0a\x1a\x0a",' ',"image/png"},
+	{0,6,"GIF87a",' ',"image/gif"},
+	{0,6,"GIF89a",' ',"image/gif"},
+	{0,8,"\xff\xd8    JFIF",' ',"image/jpeg"},
+	{0,8,"\xff\xd8    Exif",' ',"image/jpeg"},
+	{0,1,"<",' ',"text/html"},
+	{1,1,"<",' ',"text/html"},
+	{2,1,"<",' ',"text/html"},
+	{3,1,"<",' ',"text/html"},
+	{4,1,"<",' ',"text/html"},
+	{5,1,"<",' ',"text/html"},
+	{6,1,"<",' ',"text/html"},
+	{7,1,"<",' ',"text/html"},
+	{0,0,"",' ',"text/plain"},
+};
+#define MAGICREQBUFSIZE 8 
+
+#define ISHEX(x) (((x)>='0' && (x)<='9') || ((x)>='A' && (x)<='F') || ((x)>='a' && (x)<='f')) 
+#define HEX2BIN(x) (((x)>='0' && (x)<='9')?(x)-'0':((x)>='A' && (x)<='F')?(x)-'A'+10:((x)>='a' && (x)<='f')?(x)-'a'+10:0)
+
+/*
+ * Send the file screen through the IO using a pipe.
+ */
+static gint File_send_file(ChainLink *Info, DilloUrl *Urli, const char *file)
+{
+   gint FilePipe[2];
+   IOData_t *io1;
+   FileInfo_t *FileInfo;
+   struct stat stat_info;
+   int fd;
+   char *data;
+   char magic_data[MAGICREQBUFSIZE];
+   int total_read;
+   unsigned int type;
+   int i,k;
+   int header_size;
+   char *file_unscaped;
+
+   /* Get the unscaped file name */
+   if((file_unscaped=strdup(file))==NULL) {
+      MSG("File_send_file: insufficient memoryi for file name maniputation\n");
+      return -1;
+   }
+   for(i=0,k=0;file[k]!='\0';i++,k++) {
+   	if(file[k]=='%' && ISHEX(file[k+1]) && ISHEX(file[k+2])) {
+		file_unscaped[i]=((HEX2BIN(file[k+1])<<4)|HEX2BIN(file[k+2]));
+		k+=2;
+	} else 
+		file_unscaped[i]=file[k];
+   }
+   file_unscaped[i]='\0';
+   MSG("File_send_file: entered, file \"%s\"\n",file_unscaped);
+   /* Get the file info */
+   if((fd=open(file_unscaped,O_RDONLY))<=0) {
+      MSG("File_send_file: could not open \"%s\"\n",file_unscaped);
+      return -1;
+   }
+   free(file_unscaped),file_unscaped=NULL;
+
+   if((fstat(fd,&stat_info))!=0) {
+      close(fd);
+      MSG("File_send_file: could not determine file size\n");
+      return -1;
+   }
+
+   /* Identify the file */
+   memset(magic_data,0,sizeof(magic_data));
+   total_read=read(fd,magic_data,MAGICREQBUFSIZE);
+   if(total_read<0)
+   	total_read=0;
+
+   for(type=0;type<(sizeof(File_Magic)/sizeof(File_Magic[0]));type++) {
+   	for(i=0;i<File_Magic[type].Len;i++) {
+		if(magic_data[File_Magic[type].Off+i]!=File_Magic[type].Data[i] &&
+		  File_Magic[type].Data[i]!=File_Magic[type].Dont_Care)
+		   break;
+	}
+	if(i>=File_Magic[type].Len)
+		break; /* found */
+   }
+
+   if(type>=(sizeof(File_Magic)/sizeof(File_Magic[0]))) {
+   	close(fd);
+	MSG("File_send_file: type not identified\n");
+	return -1; /* not identified */
+   }
+
+   /* Get a buffer large enough for the file and header */
+   header_size=strlen(File_Magic[type].mime)+sizeof(Header_Generic1)-1+sizeof(Header_Generic2)-1;
+   if((data=malloc(stat_info.st_size+header_size))==NULL) {
+   	close(fd);
+	MSG("File_send_file: insufficient memory (requested %li bytes)\n",(long)stat_info.st_size+header_size);
+	return -1; /* insufficient memory */
+   }
+
+   /* Copy the header and the file magic */
+   i=0;
+   memcpy(data+i,Header_Generic1,sizeof(Header_Generic1)-1);
+   i+=sizeof(Header_Generic1)-1;
+   memcpy(data+i,File_Magic[type].mime,strlen(File_Magic[type].mime));
+   i+=strlen(File_Magic[type].mime);
+   memcpy(data+i,Header_Generic2,sizeof(Header_Generic2)-1);
+   i+=sizeof(Header_Generic2)-1;
+   memcpy(data+i,magic_data,total_read);
+   i+=total_read;
+
+   /* copy the reast of the file */
+   while(total_read<stat_info.st_size) {
+   	k=read(fd,data+i,stat_info.st_size-total_read);
+	if(k<=0) {
+		memset(data+i,0,stat_info.st_size-total_read);
+		break;
+	}
+	total_read+=k;
+	i+=k;
+   }
+   close(fd);
+
+   /* fire it up */
+   if (pipe(FilePipe)) 
+      return -1;
+   
+
+   FileInfo = g_new(FileInfo_t, 1);
+   FileInfo->FD_Read  = FilePipe[0];
+   FileInfo->FD_Write = FilePipe[1];
+   Info->LocalKey = FileInfo;
+
+   /* send file */
+   io1 = a_IO_new(IOWrite, FileInfo->FD_Write);
+   a_IO_set_buf(io1, data, stat_info.st_size+header_size);
+   io1->Flags |= (IOFlag_ForceClose + IOFlag_SingleWrite);
+   io1->Flags |= IOFlag_FreeIOBuf;
+   a_Chain_link_new(Info, a_File_ccc, BCK, a_IO_ccc, 1, 1);
+   a_Chain_bcb(OpStart, Info, io1, NULL);
+   a_Chain_bcb(OpSend, Info, io1, NULL);
+
+   /* Tell the cache to receive answer */
+   a_Chain_fcb(OpSend, Info, &FileInfo->FD_Read, NULL);
+   return FileInfo->FD_Read;
+}
+
+/*
+ * Push the right URL for each supported "file"
+ * ( Data1 = Requested URL; Data2 = Web structure )
+ */
+static gint File_get(ChainLink *Info, void *Data1, void *Data2)
+{
+   const char *tail;
+   DilloUrl *Url = Data1;
+   DilloWeb *web = Data2;
+
+   MSG("File_get: entered\n");
+   /* Don't allow the "file:" method for non-root URLs */
+   if (!(web->flags & WEB_RootUrl)) {
+      MSG("File_get: aborting: non-root URL\n");
+      return -1;
+   }
+
+   tail = URL_PATH(Url);
+
+   return File_send_file(Info, Url, tail);
+   return -1;
+}
+
+/*
+ * CCC function for the FILE module
+ */
+void a_File_ccc(int Op, int Branch, int Dir, ChainLink *Info,
+                 void *Data1, void *Data2)
+{
+   int FD;
+
+   a_Chain_debug_msg("a_File_ccc", Op, Branch, Dir);
+
+   if ( Branch == 1 ) {
+      /* Start file method */
+      if (Dir == BCK) {
+         switch (Op) {
+         case OpStart:
+            /* (Data1 = Url;  Data2 = Web) */
+            // Info->LocalKey gets set in File_get
+            if ((FD = File_get(Info, Data1, Data2)) == -1)
+               a_Chain_fcb(OpAbort, Info, NULL, NULL);
+            break;
+         case OpAbort:
+            a_Chain_bcb(OpAbort, Info, NULL, NULL);
+            g_free(Info->LocalKey);
+            g_free(Info);
+            break;
+         }
+      } else {  /* FWD */
+         switch (Op) {
+         case OpSend:
+            /* This means the sending framework was set OK */
+            FD = ((FileInfo_t *)Info->LocalKey)->FD_Read;
+            a_Chain_fcb(OpSend, Info, &FD, NULL);
+            break;
+         case OpEnd:
+            /* Everything sent! */
+            a_Chain_del_link(Info, BCK);
+            g_free(Info->LocalKey);
+            a_Chain_fcb(OpEnd, Info, NULL, NULL);
+            break;
+         case OpAbort:
+            g_free(Info->LocalKey);
+            a_Chain_fcb(OpAbort, Info, NULL, NULL);
+            break;
+         }
+      }
+   }
+}
+
