Index: netsurf/content/content_type.h
===================================================================
--- netsurf/content/content_type.h	(revision 12242)
+++ netsurf/content/content_type.h	(working copy)
@@ -77,6 +77,7 @@
 #ifdef WITH_APPLE_IMAGE
 	CONTENT_APPLE_IMAGE,
 #endif
+	CONTENT_GOPHER,
 	/* these must be the last two */
 	CONTENT_OTHER,
 	CONTENT_UNKNOWN  /**< content-type not received yet */
Index: netsurf/content/content.c
===================================================================
--- netsurf/content/content.c	(revision 12242)
+++ netsurf/content/content.c	(working copy)
@@ -40,6 +40,7 @@
 #include "desktop/options.h"
 #include "render/html.h"
 #include "render/textplain.h"
+#include "render/gopher.h"
 #ifdef WITH_JPEG
 #include "image/jpeg.h"
 #endif
@@ -207,6 +208,7 @@
 	{"text/css", CONTENT_CSS},
 	{"text/html", CONTENT_HTML},
 	{"text/plain", CONTENT_TEXTPLAIN},
+	{"text/x-gopher-directory", CONTENT_GOPHER},
 #ifdef WITH_MNG
 	{"video/mng", CONTENT_MNG},
 	{"video/x-mng", CONTENT_MNG},
@@ -263,6 +265,7 @@
 #ifdef WITH_APPLE_IMAGE
 	"APPLE_IMAGE",
 #endif
+	"GOPHER",
 	"OTHER",
 	"UNKNOWN"
 };
@@ -403,6 +406,9 @@
 	{0, 0, apple_image_convert, 0, apple_image_destroy, 0, 0, 0,
 		apple_image_redraw, apple_image_redraw_tiled, 0, 0, apple_image_clone, false},
 #endif
+	{gopher_create, 0, gopher_convert,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		true},
 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
 };
 #define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0]))
Index: netsurf/Makefile.sources
===================================================================
--- netsurf/Makefile.sources	(revision 12242)
+++ netsurf/Makefile.sources	(working copy)
@@ -12,7 +12,8 @@
 
 S_RENDER := box.c box_construct.c box_normalise.c favicon.c 		\
 	font.c form.c html.c html_interaction.c html_redraw.c		\
-	hubbub_binding.c imagemap.c layout.c list.c table.c textplain.c
+	hubbub_binding.c imagemap.c layout.c list.c table.c textplain.c \
+	gopher.c
 
 S_UTILS := base64.c filename.c hashtable.c http.c locale.c messages.c 	\
 	talloc.c url.c utf8.c utils.c useragent.c filepath.c log.c
Index: netsurf/render/gopher.c
===================================================================
--- netsurf/render/gopher.c	(revision 0)
+++ netsurf/render/gopher.c	(revision 0)
@@ -0,0 +1,682 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ * Copyright 2011 François Revol <mmu_man@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf 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; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for text/x-gopher-directory (implementation).
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <math.h>
+
+#include <parserutils/input/inputstream.h>
+
+#include "content/content_protected.h"
+#include "content/hlcache.h"
+#include "css/css.h"
+#include "css/utils.h"
+#include "desktop/browser.h"
+#include "desktop/gui.h"
+#include "desktop/options.h"
+#include "desktop/plotters.h"
+#include "desktop/search.h"
+#include "desktop/selection.h"
+#include "render/box.h"
+#include "render/font.h"
+#include "render/gopher.h"
+#include "utils/http.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
+#include "utils/utils.h"
+#include "utils/utf8.h"
+
+static struct {
+	char type;
+	const char *mime;
+} gopher_type_map[] = {
+	/* these come from http://tools.ietf.org/html/rfc1436 */
+	{ '0', "text/plain" },
+	{ '1', "text/x-gopher-directory;charset=UTF-8" },	/* gopher directory */
+	/* 2	CSO search */
+	/* 3	error message */
+	/* 4	binhex encoded text */
+	/* 5	binary archive file */
+	/* 6	uuencoded text */
+	{ '7', "text/x-gopher-directory;charset=UTF-8" },	/* search query */
+	/* 8	telnet: */
+	/* 9	binary */
+	{ 'g', "image/gif" },
+	{ 'h', "text/html" },
+	/* i	information text */
+	/* I	image (depends, usually jpeg) */
+	/* s	audio (wav?) */
+	/* T	tn3270 session */
+	
+	/* those are not standardized */
+	{ 'd', "application/pdf" },	/* display?? seems to be only for PDF files so far */
+	{ 0, NULL }
+};
+
+
+static char *html_escape_string(char *str)
+{
+	char *nice_str, *cnv, *tmp;
+	char *title;
+	int title_length;
+
+	if (str == NULL) {
+		return NULL;
+	}
+
+	/* Convert str for display */
+	nice_str = malloc(strlen(str) * SLEN("&amp;") + 1);
+	if (nice_str == NULL) {
+		return NULL;
+	}
+
+	/* Escape special HTML characters */
+	for (cnv = nice_str, tmp = str; *tmp != '\0'; tmp++) {
+		if (*tmp == '<') {
+			*cnv++ = '&';
+			*cnv++ = 'l';
+			*cnv++ = 't';
+			*cnv++ = ';';
+		} else if (*tmp == '>') {
+			*cnv++ = '&';
+			*cnv++ = 'g';
+			*cnv++ = 't';
+			*cnv++ = ';';
+		} else if (*tmp == '&') {
+			*cnv++ = '&';
+			*cnv++ = 'a';
+			*cnv++ = 'm';
+			*cnv++ = 'p';
+			*cnv++ = ';';
+		} else {
+			*cnv++ = *tmp;
+		}
+	}
+	*cnv = '\0';
+
+	return nice_str;
+}
+
+
+static char *gen_nice_title(char *path)
+{
+	char *nice_path, *cnv, *tmp;
+	char *title;
+	int title_length;
+
+	/* Convert path for display */
+	nice_path = malloc(strlen(path) * SLEN("&amp;") + 1);
+	if (nice_path == NULL) {
+		return NULL;
+	}
+
+	/* Escape special HTML characters */
+	for (cnv = nice_path, tmp = path; *tmp != '\0'; tmp++) {
+		if (*tmp == '<') {
+			*cnv++ = '&';
+			*cnv++ = 'l';
+			*cnv++ = 't';
+			*cnv++ = ';';
+		} else if (*tmp == '>') {
+			*cnv++ = '&';
+			*cnv++ = 'g';
+			*cnv++ = 't';
+			*cnv++ = ';';
+		} else if (*tmp == '&') {
+			*cnv++ = '&';
+			*cnv++ = 'a';
+			*cnv++ = 'm';
+			*cnv++ = 'p';
+			*cnv++ = ';';
+		} else {
+			*cnv++ = *tmp;
+		}
+	}
+	*cnv = '\0';
+
+	/* Construct a localised title string */
+	title_length = (cnv - nice_path) + strlen(messages_get("FileIndex"));
+	title = malloc(title_length + 1);
+
+	if (title == NULL) {
+		free(nice_path);
+		return NULL;
+	}
+
+	/* Set title to localised "Index of <nice_path>" */
+	snprintf(title, title_length, messages_get("FileIndex"), nice_path);
+
+	free(nice_path);
+
+	return title;
+}
+
+
+/**
+ * Convert the gopher item type to mime type
+ *
+ * \return  MIME type string
+ *
+ */
+
+const char *gopher_type_to_mime(char type)
+{
+	int i;
+
+	for (i = 0; gopher_type_map[i].type; i++)
+		if (gopher_type_map[i].type == type)
+			return gopher_type_map[i].mime;
+	return NULL;
+}
+
+
+/**
+ * Tells if the gopher item type needs to be converted to html
+ *
+ * \return  true iff the item must be converted
+ *
+ */
+
+bool gopher_need_generate(char type)
+{
+	switch (type) {
+		case '1':
+		case '7':
+			return true;
+		default:
+			return false;
+	}
+}
+
+
+/**
+ * Generates the top part of an HTML directory listing page
+ *
+ * \return  true iff buffer filled without error
+ *
+ * This is part of a series of functions.  To generate a complete page,
+ * call the following functions in order:
+ *
+ *     gopher_generate_top()
+ *     gopher_generate_title()
+ *     gopher_generate_row()           -- call 'n' times for 'n' rows
+ *     gopher_generate_bottom()
+ */
+
+static bool gopher_generate_top(char *buffer, int buffer_length)
+{
+	int error = snprintf(buffer, buffer_length,
+		"<html>\n"
+		"<head>\n"
+		/*"<!-- base href=\"%s\" -->\n"*//* XXX: needs the content url */
+		/* Don't do that:
+		 * seems to trigger a reparsing of the gopher data itself as html...
+		 * "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
+		 */
+		/* TODO: move this to clean CSS in internal.css */
+		"<link rel=\"stylesheet\" title=\"Standard\" "
+			"type=\"text/css\" href=\"resource:internal.css\">\n"
+		"<style>\n"
+		/* XXX: white-space: pre-wrap would be better but is currently buggy */
+		"span { font-family: Courier, monospace; white-space: pre; }\n"
+		"body { margin: 10px; }\n");
+	if (error < 0 || error >= buffer_length)
+		/* Error or buffer too small */
+		return false;
+	else
+		/* OK */
+		return true;
+
+}
+
+
+/**
+ * Generates the part of an HTML directory listing page that contains the title
+ *
+ * \param  title	  title to use
+ * \param  buffer	  buffer to fill with generated HTML
+ * \param  buffer_length  maximum size of buffer
+ * \return  true iff buffer filled without error
+ *
+ * This is part of a series of functions.  To generate a complete page,
+ * call the following functions in order:
+ *
+ *     gopher_generate_top()
+ *     gopher_generate_title()
+ *     gopher_generate_row()           -- call 'n' times for 'n' rows
+ *     gopher_generate_bottom()
+ */
+
+static bool gopher_generate_title(const char *title, char *buffer, int buffer_length)
+{
+	int error;
+	/*fprintf(stderr, "%s(%s, %p, %d)\n", __FUNCTION__, title, buffer, buffer_length);*/
+
+	if (title == NULL)
+		title = "";
+
+	error = snprintf(buffer, buffer_length,
+			"</style>\n"
+			"<title>%s</title>\n"
+			"</head>\n"
+			"<body id=\"gopher\">\n"
+			"<h1>%s</h1>\n",
+			title, title);
+	if (error < 0 || error >= buffer_length)
+		/* Error or buffer too small */
+		return false;
+	else
+		/* OK */
+		return true;
+}
+
+/**
+ * Internal worker called by gopher_generate_row().
+ */
+
+static bool gopher_generate_row_internal(char type, char *fields[5],
+		char *buffer, int buffer_length)
+{
+	char *nice_text;
+	char *redirect_url = NULL;
+	int error;
+	bool alt_port = false;
+	char *username = NULL;
+	/*fprintf(stderr, "%s(0x%02x '%c', {%s, %s, %s, %s}, %p, %d)\n", __FUNCTION__, type, type, fields[0], fields[1], fields[2], fields[3], buffer, buffer_length);*/
+
+	if (fields[3] && strcmp(fields[3], "70"))
+		alt_port = true;
+
+	/* escape html special characters */
+	nice_text = html_escape_string(fields[0]);
+
+	/* XXX: outputting \n generates better looking html code,
+	 * but currently screws up indentation due to a bug.
+	 */
+#define HTML_LF 
+/*#define HTML_LF "\n"*/
+
+	switch (type) {
+		case '0':	/* text/plain link */
+		case '9':	/* binary */
+			error = snprintf(buffer, buffer_length,
+			"<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+			"<span class=\"dir\">%s</span><br/>"HTML_LF
+			"</a>"HTML_LF,
+			fields[2],
+			alt_port ? ":" : "",
+			alt_port ? fields[3] : "",
+			type, fields[1], nice_text);
+			break;
+		case '1':
+			/*
+			 * directory link
+			 */
+			error = snprintf(buffer, buffer_length,
+			"<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+			"<span class=\"text\">%s</span><br/>"HTML_LF
+			"</a>"HTML_LF,
+			fields[2],
+			alt_port ? ":" : "",
+			alt_port ? fields[3] : "",
+			type, fields[1], nice_text);
+			break;
+		case '3':
+			/* Error
+			 */
+			error = snprintf(buffer, buffer_length,
+			"<span class=\"error\">%s</span><br/>"HTML_LF,
+			nice_text);
+			break;
+		case '7':
+			/* TODO: handle search better.
+			 * For now we use an unnamed input field and accept sending ?=foo
+			 * as it seems at least Veronica-2 ignores the = but it's unclean.
+			 */
+			error = snprintf(buffer, buffer_length,
+			"<form method=\"get\" action=\"gopher://%s%s%s/%c%s\">"HTML_LF
+			"<span class=\"query\"><label>%s <input name=\"\" type=\"text\" align=\"right\" /></label></span><br/>"HTML_LF
+			"</form>"HTML_LF,
+			fields[2],
+			alt_port ? ":" : "",
+			alt_port ? fields[3] : "",
+			type, fields[1], nice_text);
+			break;
+		case '8':
+			/* telnet: links
+			 * cf. gopher://78.80.30.202/1/ps3
+			 * -> gopher://78.80.30.202:23/8/ps3/new -> new@78.80.30.202
+			 */
+			alt_port = false;
+			if (fields[3] && strcmp(fields[3], "23"))
+				alt_port = true;
+			username = strrchr(fields[1], '/');
+			if (username)
+				username++;
+			error = snprintf(buffer, buffer_length,
+			"<a href=\"telnet://%s%s%s%s%s\">"HTML_LF
+			"<span class=\"dir\">%s</span><br/>"HTML_LF
+			"</a>"HTML_LF,
+			username ? username : "",
+			username ? "@" : "",
+			fields[2],
+			alt_port ? ":" : "",
+			alt_port ? fields[3] : "",
+			nice_text);
+			break;
+		case 'g':
+		case 'I':
+			/* quite dangerous, cf. gopher://namcub.accela-labs.com/1/pics */
+			if (option_gopher_inline_images) {
+				error = snprintf(buffer, buffer_length,
+				"<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+				"<span class=\"img\">%s "HTML_LF /* </span><br/> */
+				//"<span class=\"img\" >"HTML_LF
+				"<img src=\"gopher://%s%s%s/%c%s\" alt=\"%s\"/>"HTML_LF
+				"</span>"
+				"<br/>"
+				"</a>"HTML_LF,
+				fields[2],
+				alt_port ? ":" : "",
+				alt_port ? fields[3] : "",
+				type, fields[1],
+				nice_text,
+				fields[2],
+				alt_port ? ":" : "",
+				alt_port ? fields[3] : "",
+				type, fields[1],
+				nice_text);
+				break;
+			}
+			/* fallback to default, link them */
+			error = snprintf(buffer, buffer_length,
+			"<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+			"<span class=\"dir\">%s</span><br/>"HTML_LF
+			"</a>"HTML_LF,
+			fields[2],
+			alt_port ? ":" : "",
+			alt_port ? fields[3] : "",
+			type, fields[1], nice_text);
+			break;
+		case 'h':
+			if (fields[1] && strncmp(fields[1], "URL:", 4) == 0)
+				redirect_url = fields[1] + 4;
+			/* cf. gopher://pineapple.vg/1 */
+			if (fields[1] && strncmp(fields[1], "/URL:", 5) == 0)
+				redirect_url = fields[1] + 5;
+			if (redirect_url) {
+				error = snprintf(buffer, buffer_length,
+				"<a href=\"%s\">"HTML_LF
+				"<span class=\"link\">%s</span><br/>"HTML_LF
+				"</a>"HTML_LF,
+				redirect_url,
+				nice_text);
+			} else {
+				/* cf. gopher://sdf.org/1/sdf/classes/ */
+				error = snprintf(buffer, buffer_length,
+				"<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+				"<span class=\"dir\">%s</span><br/>"HTML_LF
+				"</a>"HTML_LF,
+				fields[2],
+				alt_port ? ":" : "",
+				alt_port ? fields[3] : "",
+				type, fields[1], nice_text);
+			}
+			break;
+		case 'i':
+			error = snprintf(buffer, buffer_length,
+			"<span class=\"info\">%s</span><br/>"HTML_LF,
+			nice_text);
+			break;
+		default:
+			fprintf(stderr, "warning: unknown gopher item type 0x%02x '%c'\n", type, type);
+			error = snprintf(buffer, buffer_length,
+			"<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+			"<span class=\"dir\">%s</span><br/>"HTML_LF
+			"</a>"HTML_LF,
+			fields[2],
+			alt_port ? ":" : "",
+			alt_port ? fields[3] : "",
+			type, fields[1], nice_text);
+			break;
+	}
+
+	free(nice_text);
+
+	if (error < 0 || error >= buffer_length)
+		/* Error or buffer too small */
+		return false;
+	else
+		/* OK */
+		return true;
+}
+
+
+/**
+ * Generates the part of an HTML directory listing page that displays a row
+ * of the gopher data
+ *
+ * \param  size		  pointer to the data buffer pointer
+ * \param  size		  pointer to the remaining data size
+ * \param  buffer	  buffer to fill with generated HTML
+ * \param  buffer_length  maximum size of buffer
+ * \return  true iff buffer filled without error
+ *
+ * This is part of a series of functions.  To generate a complete page,
+ * call the following functions in order:
+ *
+ *     gopher_generate_top()
+ *     gopher_generate_title()
+ *     gopher_generate_row()           -- call 'n' times for 'n' rows
+ *     gopher_generate_bottom()
+ */
+
+static bool gopher_generate_row(char **data, size_t *size,
+		char *buffer, int buffer_length)
+{
+	bool ok = false;
+	char type = 0;
+	int field = 0;
+	/* name, selector, host, port, gopher+ flag */
+	char *fields[5] = { NULL, NULL, NULL, NULL, NULL };
+	char *s = *data;
+	char *p = *data;
+	int i;
+	/*fprintf(stderr, "%s(, &%d, %p, %d)\n", __FUNCTION__, *size, buffer, buffer_length);*/
+
+	for (; *size && *p; p++, (*size)--) {
+		if (!type) {
+			type = *p;
+			if (!type || type == '\n' || type == '\r') {
+				fprintf(stderr, "warning: invalid gopher item type 0x%02x\n", type);
+			}
+			/* TODO: check it's really alone on its line */
+			/*
+			if (type == '.')
+				return false;
+			*/
+			s++;
+			continue;
+		}
+		switch (*p) {
+			case '\n':
+				/*fprintf(stderr, "case '\\x%02x':\n", *p);*/
+				if (field > 0) {
+					fprintf(stderr, "warning: underminated gopher item '%c'\n", type);
+				}
+				//FALLTHROUGH
+			case '\r':
+				/*fprintf(stderr, "case '\\x%02x':\n", *p);*/
+				if (*size < 1 || p[1] != '\n') {
+					fprintf(stderr, "warning: CR without LF in gopher item '%c'\n", type);
+				}
+				//TODO: check gopher://gopher.floodgap.com/1/overbite/dbrowse?pluginm
+				// (1 extra field ??)
+				if (field < 3) {
+					fprintf(stderr, "warning: underminated gopher item '%c'\n", type);
+				}
+				fields[field] = malloc(p - s + 1);
+				memcpy(fields[field], s, p - s);
+				fields[field][p - s] = '\0';
+				if (type == '.' && field == 0 && p == s) {
+					;/* TODO: signal end of page */
+				}
+				ok = gopher_generate_row_internal(type, fields, buffer, buffer_length);
+				for (i = 0; i < 5; i++) {
+					free(fields[i]);
+					fields[i] = NULL;
+				}
+				/*fprintf(stderr, "ret: row %sok *size=%d\n", ok ? "" : "not ", *size);*/
+				(*size)--;
+				p++;
+				if (*size && *p == '\n') {
+					p++;
+					(*size)--;
+				}
+				*data = p;
+				field = 0;
+				//break;
+				return ok;
+			case '\x09':
+				/*fprintf(stderr, "case '\\x%02x':\n", *p);*/
+				if (field >= 4) {
+					fprintf(stderr, "warning: extra tab in gopher item '%c'\n", type);
+					break;
+				}
+				fields[field] = malloc(p - s + 1);
+				memcpy(fields[field], s, p - s);
+				fields[field][p - s] = '\0';
+				field++;
+				s = p + 1;
+				break;
+			default:
+				break;
+		}
+	}
+
+	return false;
+}
+
+
+/**
+ * Generates the bottom part of an HTML directory listing page
+ *
+ * \return  Bottom of directory listing HTML
+ *
+ * This is part of a series of functions.  To generate a complete page,
+ * call the following functions in order:
+ *
+ *     gopher_generate_top()
+ *     gopher_generate_title()
+ *     gopher_generate_row()           -- call 'n' times for 'n' rows
+ *     gopher_generate_bottom()
+ */
+
+static bool gopher_generate_bottom(char *buffer, int buffer_length)
+{
+	int error = snprintf(buffer, buffer_length,
+			"</div>\n"
+			"</body>\n"
+			"</html>\n");
+	/*fprintf(stderr, "%s(%p, %d)\n", __FUNCTION__, buffer, buffer_length);*/
+	if (error < 0 || error >= buffer_length)
+		/* Error or buffer too small */
+		return false;
+	else
+		/* OK */
+		return true;
+}
+
+
+
+
+/**
+ * Create a CONTENT_GOPHER.
+ */
+
+bool gopher_create(struct content *c, const http_parameter *params)
+{
+	bool ok;
+	ok = html_create(c, params);
+	return ok;
+}
+
+
+/**
+ * Convert a CONTENT_GOPHER for display.
+ */
+
+bool gopher_convert(struct content *c)
+{
+	char *title;
+	char buffer[1024];
+	char *data;
+	unsigned long size;
+	char *p;
+	size_t left;
+	bool ok;
+	/*fprintf(stderr, "%s()\n", __FUNCTION__);*/
+
+	data = content__get_source_data(c, &size);
+
+	p = data;
+	left = size;
+	if (data == NULL || size == 0)
+		return false;
+
+	if (gopher_generate_bottom(buffer, sizeof(buffer))) {
+		ok = html_process_data(c, buffer, strlen(buffer));
+		if (!ok)
+			return false;
+	}
+	if (gopher_generate_top(buffer, sizeof(buffer))) {
+		ok = html_process_data(c, buffer, strlen(buffer));
+		if (!ok)
+			return false;
+	}
+	title = gen_nice_title(content__get_url(c));
+	if (gopher_generate_title(title, buffer, sizeof(buffer))) {
+		ok = html_process_data(c, buffer, strlen(buffer));
+		if (!ok)
+			return false;
+	}
+	free(title);
+
+	while (gopher_generate_row(&p, &left, buffer, sizeof(buffer))) {
+		ok = html_process_data(c, buffer, strlen(buffer));
+		if (!ok)
+			return false;
+		gui_multitask();
+	}
+
+	/* finally make it HTML so we don't have to bother for other calls */
+	c->type = CONTENT_HTML;
+	return html_convert(c);
+}
+
+
Index: netsurf/render/gopher.h
===================================================================
--- netsurf/render/gopher.h	(revision 0)
+++ netsurf/render/gopher.h	(revision 0)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ * Copyright 2011 François Revol <mmu_man@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf 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; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for text/x-gopher-directory (interface).
+ */
+
+#ifndef _NETSURF_RENDER_GOPHER_H_
+#define _NETSURF_RENDER_GOPHER_H_
+
+#include <stddef.h>
+
+struct content;
+struct http_parameter;
+
+bool gopher_create(struct content *c, const struct http_parameter *params);
+bool gopher_process_data(struct content *c, 
+		const char *data, unsigned int size);
+bool gopher_convert(struct content *c);
+
+
+const char *gopher_type_to_mime(char type);
+bool gopher_need_generate(char type);
+
+#endif
