Index: netsurf/content/fetchers/curl.c
===================================================================
--- netsurf/content/fetchers/curl.c	(revision 12242)
+++ netsurf/content/fetchers/curl.c	(working copy)
@@ -44,6 +44,7 @@
 #include "content/urldb.h"
 #include "desktop/netsurf.h"
 #include "desktop/options.h"
+#include "render/gopher.h"
 #include "utils/log.h"
 #include "utils/messages.h"
 #include "utils/schedule.h"
@@ -72,6 +73,7 @@
 	bool abort;		/**< Abort requested. */
 	bool stopped;		/**< Download stopped on purpose. */
 	bool only_2xx;		/**< Only HTTP 2xx responses acceptable. */
+	bool gopher_type;	/**< Indicates the type of document for gopher: url */
 	char *url;		/**< URL of this fetch. */
 	char *host;		/**< The hostname of this fetch. */
 	struct curl_slist *headers;	/**< List of request headers. */
@@ -111,6 +113,10 @@
 		 bool only_2xx, const char *post_urlenc,
 		 const struct fetch_multipart_data *post_multipart,
 		 const char **headers);
+static void * fetch_curl_setup_gopher(struct fetch *parent_fetch, const char *url,
+		 bool only_2xx, const char *post_urlenc,
+		 const struct fetch_multipart_data *post_multipart,
+		 const char **headers);
 static bool fetch_curl_start(void *vfetch);
 static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
 		CURL *handle);
@@ -220,14 +226,19 @@
 	data = curl_version_info(CURLVERSION_NOW);
 
 	for (i = 0; data->protocols[i]; i++) {
+		fetcher_setup_fetch setup_hook;
 		/* Ignore non-http(s) protocols */
-		if (strcmp(data->protocols[i], "http") != 0 &&
-				strcmp(data->protocols[i], "https") != 0)
+		if (strcmp(data->protocols[i], "http") == 0 ||
+				strcmp(data->protocols[i], "https") == 0)
+			setup_hook = fetch_curl_setup;
+		else if (strcmp(data->protocols[i], "gopher") == 0)
+			setup_hook = fetch_curl_setup_gopher;
+		else
 			continue;
 
 		if (!fetch_add_fetcher(data->protocols[i],
 				       fetch_curl_initialise,
-				       fetch_curl_setup,
+				       setup_hook,
 				       fetch_curl_start,
 				       fetch_curl_abort,
 				       fetch_curl_free,
@@ -339,6 +350,7 @@
 	fetch->abort = false;
 	fetch->stopped = false;
 	fetch->only_2xx = only_2xx;
+	fetch->gopher_type = 0;
 	fetch->url = strdup(url);
 	fetch->headers = 0;
 	fetch->host = host;
@@ -410,6 +422,41 @@
 }
 
 
+void * fetch_curl_setup_gopher(struct fetch *parent_fetch, const char *url,
+		 bool only_2xx, const char *post_urlenc,
+		 const struct fetch_multipart_data *post_multipart,
+		 const char **headers)
+{
+	struct curl_fetch_info *f;
+	const char *mime;
+	char type;
+	f = fetch_curl_setup(parent_fetch, url, only_2xx, post_urlenc,
+		 post_multipart, headers);
+	if (url_gopher_type(url, &type) == URL_FUNC_OK && type)
+		f->gopher_type = type;
+	else
+		f->http_code = 404;
+
+	mime = gopher_type_to_mime(type);
+	/* TODO: add a fetch_mimetype_by_ext() or fetch_mimetype_sniff_data() */
+	/*
+	if (mime == NULL)
+		mime = "application/octet-stream";
+	*/
+
+	if (mime) {
+		char s[80];
+		/* fprintf(stderr, "gopher mime is '%s'\n", mime); */
+		snprintf(s, sizeof s, "Content-type: %s\r\n", mime);
+		s[sizeof s - 1] = 0;
+		fetch_send_callback(FETCH_HEADER, f->fetch_handle, s, strlen(s),
+				FETCH_ERROR_NO_ERROR);
+	}
+
+	return f;
+}
+
+
 /**
  * Dispatch a single job
  */
@@ -771,6 +818,8 @@
 	LOG(("done %s", f->url));
 
 	if (abort_fetch == false && result == CURLE_OK) {
+		//if (f->gopher_type)
+			//fetch_curl_gopher_data(NULL, 0, 0, f);
 		/* fetch completed normally */
 		if (f->stopped ||
 				(!f->had_headers &&
@@ -978,6 +1027,22 @@
 	struct curl_fetch_info *f = _f;
 	CURLcode code;
 
+	/* gopher data receives special treatment */
+	if (f->gopher_type && gopher_need_generate(f->gopher_type)) {
+		/* type 3 items report an error */
+		if (!f->http_code) {
+			if (data[0] == '3') {
+				/* TODO: try to guess better from the string ?
+				 * like "3 '/bcd' doesn't exist!"
+				 * TODO: what about other file types ?
+				 */
+				f->http_code = 404;
+			} else {
+				f->http_code = 200;
+			}
+		}
+	}
+
 	/* ensure we only have to get this information once */
 	if (!f->http_code)
 	{
