commit 9a6ec2f469d556077f81b5b64e24c64fd0d5e3c4 Author: Luboš Uhliarik Date: Wed Dec 6 10:38:39 2023 +0100 Remove gopher support diff --git a/doc/debug-sections.txt b/doc/debug-sections.txt index a1be7fe..c9f99b0 100644 --- a/doc/debug-sections.txt +++ b/doc/debug-sections.txt @@ -28,7 +28,6 @@ section 06 Disk I/O Routines section 07 Multicast section 08 Swap File Bitmap section 09 File Transfer Protocol (FTP) -section 10 Gopher section 11 Hypertext Transfer Protocol (HTTP) section 12 Internet Cache Protocol (ICP) section 13 High Level Memory Pool Management diff --git a/errors/en/ERR_UNSUP_REQ b/errors/en/ERR_UNSUP_REQ index 659d6de..433fd11 100644 --- a/errors/en/ERR_UNSUP_REQ +++ b/errors/en/ERR_UNSUP_REQ @@ -24,7 +24,7 @@ body

Unsupported Request Method and Protocol

-

Squid does not support all request methods for all access protocols. For example, you can not POST a Gopher request.

+

Squid does not support all request methods for all access protocols.

Your cache administrator is %w.


diff --git a/errors/errorpage.css b/errors/errorpage.css index 5e4fd47..5f12619 100644 --- a/errors/errorpage.css +++ b/errors/errorpage.css @@ -73,7 +73,7 @@ p { pre { } -/* special event: FTP / Gopher directory listing */ +/* special event: FTP directory listing */ #dirmsg { font-family: courier, monospace; color: black; diff --git a/errors/templates/ERR_UNSUP_REQ b/errors/templates/ERR_UNSUP_REQ index b2310ae..7cc4e20 100644 --- a/errors/templates/ERR_UNSUP_REQ +++ b/errors/templates/ERR_UNSUP_REQ @@ -24,7 +24,7 @@ body

Unsupported Request Method and Protocol

-

Squid does not support all request methods for all access protocols. For example, you can not POST a Gopher request.

+

Squid does not support all request methods for all access protocols.

Your cache administrator is %w.


diff --git a/src/FwdState.cc b/src/FwdState.cc index e493a88..c089f82 100644 --- a/src/FwdState.cc +++ b/src/FwdState.cc @@ -29,7 +29,6 @@ #include "fde.h" #include "FwdState.h" #include "globals.h" -#include "gopher.h" #include "HappyConnOpener.h" #include "hier_code.h" #include "http.h" @@ -1281,10 +1280,6 @@ FwdState::dispatch() httpStart(this); break; - case AnyP::PROTO_GOPHER: - gopherStart(this); - break; - case AnyP::PROTO_FTP: if (request->flags.ftpNative) Ftp::StartRelay(this); diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index fd20600..1b4e337 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -19,7 +19,6 @@ #include "Downloader.h" #include "error/Detail.h" #include "globals.h" -#include "gopher.h" #include "http.h" #include "http/ContentLengthInterpreter.h" #include "http/one/RequestParser.h" @@ -560,11 +559,6 @@ HttpRequest::maybeCacheable() return false; break; - case AnyP::PROTO_GOPHER: - if (!gopherCachable(this)) - return false; - break; - case AnyP::PROTO_CACHE_OBJECT: return false; diff --git a/src/IoStats.h b/src/IoStats.h index 96f64f5..886607a 100644 --- a/src/IoStats.h +++ b/src/IoStats.h @@ -22,7 +22,7 @@ public: int writes; int write_hist[histSize]; } - Http, Ftp, Gopher; + Http, Ftp; }; #endif /* SQUID_IOSTATS_H_ */ diff --git a/src/Makefile.am b/src/Makefile.am index c331be4..76a1ac1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -410,8 +410,6 @@ squid_SOURCES = \ fs_io.cc \ fs_io.h \ globals.h \ - gopher.cc \ - gopher.h \ helper.cc \ helper.h \ hier_code.h \ @@ -1966,8 +1964,6 @@ tests_test_http_range_SOURCES = \ fqdncache.h \ fs_io.cc \ fs_io.h \ - tests/stub_gopher.cc \ - gopher.h \ helper.cc \ hier_code.h \ http.cc \ @@ -2356,8 +2352,6 @@ tests_testHttpRequest_SOURCES = \ fqdncache.h \ fs_io.cc \ fs_io.h \ - tests/stub_gopher.cc \ - gopher.h \ helper.cc \ hier_code.h \ http.cc \ @@ -2662,8 +2656,6 @@ tests_testCacheManager_SOURCES = \ fqdncache.h \ fs_io.cc \ fs_io.h \ - tests/stub_gopher.cc \ - gopher.h \ helper.cc \ hier_code.h \ http.cc \ diff --git a/src/adaptation/ecap/Host.cc b/src/adaptation/ecap/Host.cc index edb55de..b1d8a8d 100644 --- a/src/adaptation/ecap/Host.cc +++ b/src/adaptation/ecap/Host.cc @@ -49,7 +49,6 @@ Adaptation::Ecap::Host::Host() libecap::protocolHttp.assignHostId(AnyP::PROTO_HTTP); libecap::protocolHttps.assignHostId(AnyP::PROTO_HTTPS); libecap::protocolFtp.assignHostId(AnyP::PROTO_FTP); - libecap::protocolGopher.assignHostId(AnyP::PROTO_GOPHER); libecap::protocolWais.assignHostId(AnyP::PROTO_WAIS); libecap::protocolUrn.assignHostId(AnyP::PROTO_URN); libecap::protocolWhois.assignHostId(AnyP::PROTO_WHOIS); diff --git a/src/adaptation/ecap/MessageRep.cc b/src/adaptation/ecap/MessageRep.cc index c5ade9c..cd543bd 100644 --- a/src/adaptation/ecap/MessageRep.cc +++ b/src/adaptation/ecap/MessageRep.cc @@ -140,8 +140,6 @@ Adaptation::Ecap::FirstLineRep::protocol() const return libecap::protocolHttps; case AnyP::PROTO_FTP: return libecap::protocolFtp; - case AnyP::PROTO_GOPHER: - return libecap::protocolGopher; case AnyP::PROTO_WAIS: return libecap::protocolWais; case AnyP::PROTO_WHOIS: diff --git a/src/anyp/ProtocolType.h b/src/anyp/ProtocolType.h index e736c19..a233da5 100644 --- a/src/anyp/ProtocolType.h +++ b/src/anyp/ProtocolType.h @@ -27,7 +27,6 @@ typedef enum { PROTO_HTTPS, PROTO_COAP, PROTO_COAPS, - PROTO_GOPHER, PROTO_WAIS, PROTO_CACHE_OBJECT, PROTO_ICP, diff --git a/src/anyp/Uri.cc b/src/anyp/Uri.cc index e5ae0ae..20b9bf1 100644 --- a/src/anyp/Uri.cc +++ b/src/anyp/Uri.cc @@ -879,8 +879,6 @@ urlCheckRequest(const HttpRequest * r) if (r->method == Http::METHOD_PUT) rc = 1; - case AnyP::PROTO_GOPHER: - case AnyP::PROTO_WAIS: case AnyP::PROTO_WHOIS: diff --git a/src/anyp/UriScheme.cc b/src/anyp/UriScheme.cc index 7f11537..81079fd 100644 --- a/src/anyp/UriScheme.cc +++ b/src/anyp/UriScheme.cc @@ -87,9 +87,6 @@ AnyP::UriScheme::defaultPort() const // Assuming IANA policy of allocating same port for base and TLS protocol versions will occur. return 5683; - case AnyP::PROTO_GOPHER: - return 70; - case AnyP::PROTO_WAIS: return 210; diff --git a/src/cf.data.pre b/src/cf.data.pre index 7de09e9..67a66b0 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -4779,7 +4779,7 @@ DOC_START [http::]url.getScheme() == AnyP::PROTO_HTTP) return method.respMaybeCacheable(); - if (request->url.getScheme() == AnyP::PROTO_GOPHER) - return gopherCachable(request); - if (request->url.getScheme() == AnyP::PROTO_CACHE_OBJECT) return 0; diff --git a/src/error/forward.h b/src/error/forward.h index b14a6ee..c105a66 100644 --- a/src/error/forward.h +++ b/src/error/forward.h @@ -67,7 +67,7 @@ typedef enum { ERR_GATEWAY_FAILURE, /* Special Cases */ - ERR_DIR_LISTING, /* Display of remote directory (FTP, Gopher) */ + ERR_DIR_LISTING, /* Display of remote directory (FTP) */ ERR_SQUID_SIGNATURE, /* not really an error */ ERR_SHUTTING_DOWN, ERR_PROTOCOL_UNKNOWN, diff --git a/src/gopher.cc b/src/gopher.cc deleted file mode 100644 index 2645b6b..0000000 --- a/src/gopher.cc +++ /dev/null @@ -1,976 +0,0 @@ -/* - * Copyright (C) 1996-2022 The Squid Software Foundation and contributors - * - * Squid software is distributed under GPLv2+ license and includes - * contributions from numerous individuals and organizations. - * Please see the COPYING and CONTRIBUTORS files for details. - */ - -/* DEBUG: section 10 Gopher */ - -#include "squid.h" -#include "comm.h" -#include "comm/Read.h" -#include "comm/Write.h" -#include "errorpage.h" -#include "fd.h" -#include "FwdState.h" -#include "globals.h" -#include "html_quote.h" -#include "HttpReply.h" -#include "HttpRequest.h" -#include "MemBuf.h" -#include "mime.h" -#include "parser/Tokenizer.h" -#include "rfc1738.h" -#include "SquidConfig.h" -#include "SquidTime.h" -#include "StatCounters.h" -#include "Store.h" -#include "tools.h" - -#if USE_DELAY_POOLS -#include "DelayPools.h" -#include "MemObject.h" -#endif - -/* gopher type code from rfc. Anawat. */ -#define GOPHER_FILE '0' -#define GOPHER_DIRECTORY '1' -#define GOPHER_CSO '2' -#define GOPHER_ERROR '3' -#define GOPHER_MACBINHEX '4' -#define GOPHER_DOSBIN '5' -#define GOPHER_UUENCODED '6' -#define GOPHER_INDEX '7' -#define GOPHER_TELNET '8' -#define GOPHER_BIN '9' -#define GOPHER_REDUNT '+' -#define GOPHER_3270 'T' -#define GOPHER_GIF 'g' -#define GOPHER_IMAGE 'I' - -#define GOPHER_HTML 'h' -#define GOPHER_INFO 'i' - -/// W3 address -#define GOPHER_WWW 'w' -#define GOPHER_SOUND 's' - -#define GOPHER_PLUS_IMAGE ':' -#define GOPHER_PLUS_MOVIE ';' -#define GOPHER_PLUS_SOUND '<' - -#define GOPHER_PORT 70 - -#define TAB '\t' - -// TODO CODE: should this be a protocol-specific thing? -#define TEMP_BUF_SIZE 4096 - -#define MAX_CSO_RESULT 1024 - -/** - * Gopher Gateway Internals - * - * Gopher is somewhat complex and gross because it must convert from - * the Gopher protocol to HTTP. - */ -class GopherStateData -{ - CBDATA_CLASS(GopherStateData); - -public: - GopherStateData(FwdState *aFwd) : - entry(aFwd->entry), - conversion(NORMAL), - HTML_header_added(0), - HTML_pre(0), - type_id(GOPHER_FILE /* '0' */), - overflowed(false), - cso_recno(0), - len(0), - buf(NULL), - fwd(aFwd) - { - *request = 0; - buf = (char *)memAllocate(MEM_4K_BUF); - entry->lock("gopherState"); - *replybuf = 0; - } - - ~GopherStateData(); - -public: - StoreEntry *entry; - enum { - NORMAL, - HTML_DIR, - HTML_INDEX_RESULT, - HTML_CSO_RESULT, - HTML_INDEX_PAGE, - HTML_CSO_PAGE - } conversion; - int HTML_header_added; - int HTML_pre; - char type_id; - char request[MAX_URL]; - - /// some received bytes ignored due to internal buffer capacity limits - bool overflowed; - - int cso_recno; - - /// the number of not-yet-parsed Gopher line bytes in this->buf - int len; - - char *buf; /* pts to a 4k page */ - Comm::ConnectionPointer serverConn; - FwdState::Pointer fwd; - HttpReply::Pointer reply_; - char replybuf[BUFSIZ]; -}; - -CBDATA_CLASS_INIT(GopherStateData); - -static CLCB gopherStateFree; -static void gopherMimeCreate(GopherStateData *); -static void gopher_request_parse(const HttpRequest * req, - char *type_id, - char *request); -static void gopherEndHTML(GopherStateData *); -static void gopherToHTML(GopherStateData *, char *inbuf, int len); -static CTCB gopherTimeout; -static IOCB gopherReadReply; -static IOCB gopherSendComplete; -static PF gopherSendRequest; - -static char def_gopher_bin[] = "www/unknown"; - -static char def_gopher_text[] = "text/plain"; - -static void -gopherStateFree(const CommCloseCbParams ¶ms) -{ - GopherStateData *gopherState = (GopherStateData *)params.data; - // Assume that FwdState is monitoring and calls noteClosure(). See XXX about - // Connection sharing with FwdState in gopherStart(). - delete gopherState; -} - -GopherStateData::~GopherStateData() -{ - if (entry) - entry->unlock("gopherState"); - - if (buf) - memFree(buf, MEM_4K_BUF); -} - -/** - * Create MIME Header for Gopher Data - */ -static void -gopherMimeCreate(GopherStateData * gopherState) -{ - StoreEntry *entry = gopherState->entry; - const char *mime_type = NULL; - const char *mime_enc = NULL; - - switch (gopherState->type_id) { - - case GOPHER_DIRECTORY: - - case GOPHER_INDEX: - - case GOPHER_HTML: - - case GOPHER_WWW: - - case GOPHER_CSO: - mime_type = "text/html"; - break; - - case GOPHER_GIF: - - case GOPHER_IMAGE: - - case GOPHER_PLUS_IMAGE: - mime_type = "image/gif"; - break; - - case GOPHER_SOUND: - - case GOPHER_PLUS_SOUND: - mime_type = "audio/basic"; - break; - - case GOPHER_PLUS_MOVIE: - mime_type = "video/mpeg"; - break; - - case GOPHER_MACBINHEX: - - case GOPHER_DOSBIN: - - case GOPHER_UUENCODED: - - case GOPHER_BIN: - /* Rightnow We have no idea what it is. */ - mime_enc = mimeGetContentEncoding(gopherState->request); - mime_type = mimeGetContentType(gopherState->request); - if (!mime_type) - mime_type = def_gopher_bin; - break; - - case GOPHER_FILE: - - default: - mime_enc = mimeGetContentEncoding(gopherState->request); - mime_type = mimeGetContentType(gopherState->request); - if (!mime_type) - mime_type = def_gopher_text; - break; - } - - assert(entry->isEmpty()); - - HttpReply *reply = new HttpReply; - entry->buffer(); - reply->setHeaders(Http::scOkay, "Gatewaying", mime_type, -1, -1, -2); - if (mime_enc) - reply->header.putStr(Http::HdrType::CONTENT_ENCODING, mime_enc); - - entry->replaceHttpReply(reply); - gopherState->reply_ = reply; -} - -/** - * Parse a gopher request into components. By Anawat. - */ -static void -gopher_request_parse(const HttpRequest * req, char *type_id, char *request) -{ - ::Parser::Tokenizer tok(req->url.path()); - - if (request) - *request = 0; - - tok.skip('/'); // ignore failures? path could be ab-empty - - if (tok.atEnd()) { - *type_id = GOPHER_DIRECTORY; - return; - } - - static const CharacterSet anyByte("UTF-8",0x00, 0xFF); - - SBuf typeId; - (void)tok.prefix(typeId, anyByte, 1); // never fails since !atEnd() - *type_id = typeId[0]; - - if (request) { - SBufToCstring(request, tok.remaining().substr(0, MAX_URL-1)); - /* convert %xx to char */ - rfc1738_unescape(request); - } -} - -/** - * Parse the request to determine whether it is cachable. - * - * \param req Request data. - * \retval 0 Not cachable. - * \retval 1 Cachable. - */ -int -gopherCachable(const HttpRequest * req) -{ - int cachable = 1; - char type_id; - /* parse to see type */ - gopher_request_parse(req, - &type_id, - NULL); - - switch (type_id) { - - case GOPHER_INDEX: - - case GOPHER_CSO: - - case GOPHER_TELNET: - - case GOPHER_3270: - cachable = 0; - break; - - default: - cachable = 1; - } - - return cachable; -} - -static void -gopherHTMLHeader(StoreEntry * e, const char *title, const char *substring) -{ - storeAppendPrintf(e, "\n"); - storeAppendPrintf(e, ""); - storeAppendPrintf(e, title, substring); - storeAppendPrintf(e, ""); - storeAppendPrintf(e, "\n"); - storeAppendPrintf(e, "\n

"); - storeAppendPrintf(e, title, substring); - storeAppendPrintf(e, "

\n"); -} - -static void -gopherHTMLFooter(StoreEntry * e) -{ - storeAppendPrintf(e, "
\n"); - storeAppendPrintf(e, "
\n"); - storeAppendPrintf(e, "Generated %s by %s (%s)\n", - mkrfc1123(squid_curtime), - getMyHostname(), - visible_appname_string); - storeAppendPrintf(e, "
\n"); -} - -static void -gopherEndHTML(GopherStateData * gopherState) -{ - StoreEntry *e = gopherState->entry; - - if (!gopherState->HTML_header_added) { - gopherHTMLHeader(e, "Server Return Nothing", NULL); - storeAppendPrintf(e, "

The Gopher query resulted in a blank response

"); - } else if (gopherState->HTML_pre) { - storeAppendPrintf(e, "\n"); - } - - gopherHTMLFooter(e); -} - -/** - * Convert Gopher to HTML. - * - * Borrow part of code from libwww2 came with Mosaic distribution. - */ -static void -gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) -{ - char *pos = inbuf; - char *lpos = NULL; - char *tline = NULL; - LOCAL_ARRAY(char, line, TEMP_BUF_SIZE); - char *name = NULL; - char *selector = NULL; - char *host = NULL; - char *port = NULL; - char *escaped_selector = NULL; - const char *icon_url = NULL; - char gtype; - StoreEntry *entry = NULL; - - memset(line, '\0', TEMP_BUF_SIZE); - - entry = gopherState->entry; - - if (gopherState->conversion == GopherStateData::HTML_INDEX_PAGE) { - char *html_url = html_quote(entry->url()); - gopherHTMLHeader(entry, "Gopher Index %s", html_url); - storeAppendPrintf(entry, - "

This is a searchable Gopher index. Use the search\n" - "function of your browser to enter search terms.\n" - "\n"); - gopherHTMLFooter(entry); - /* now let start sending stuff to client */ - entry->flush(); - gopherState->HTML_header_added = 1; - - return; - } - - if (gopherState->conversion == GopherStateData::HTML_CSO_PAGE) { - char *html_url = html_quote(entry->url()); - gopherHTMLHeader(entry, "CSO Search of %s", html_url); - storeAppendPrintf(entry, - "

A CSO database usually contains a phonebook or\n" - "directory. Use the search function of your browser to enter\n" - "search terms.

\n"); - gopherHTMLFooter(entry); - /* now let start sending stuff to client */ - entry->flush(); - gopherState->HTML_header_added = 1; - - return; - } - - SBuf outbuf; - - if (!gopherState->HTML_header_added) { - if (gopherState->conversion == GopherStateData::HTML_CSO_RESULT) - gopherHTMLHeader(entry, "CSO Search Result", NULL); - else - gopherHTMLHeader(entry, "Gopher Menu", NULL); - - outbuf.append ("
");
-
-        gopherState->HTML_header_added = 1;
-
-        gopherState->HTML_pre = 1;
-    }
-
-    while (pos < inbuf + len) {
-        int llen;
-        int left = len - (pos - inbuf);
-        lpos = (char *)memchr(pos, '\n', left);
-        if (lpos) {
-            ++lpos;             /* Next line is after \n */
-            llen = lpos - pos;
-        } else {
-            llen = left;
-        }
-        if (gopherState->len + llen >= TEMP_BUF_SIZE) {
-            debugs(10, DBG_IMPORTANT, "GopherHTML: Buffer overflow. Lost some data on URL: " << entry->url()  );
-            llen = TEMP_BUF_SIZE - gopherState->len - 1;
-            gopherState->overflowed = true; // may already be true
-        }
-        if (!lpos) {
-            /* there is no complete line in inbuf */
-            /* copy it to temp buffer */
-            /* note: llen is adjusted above */
-            memcpy(gopherState->buf + gopherState->len, pos, llen);
-            gopherState->len += llen;
-            break;
-        }
-        if (gopherState->len != 0) {
-            /* there is something left from last tx. */
-            memcpy(line, gopherState->buf, gopherState->len);
-            memcpy(line + gopherState->len, pos, llen);
-            llen += gopherState->len;
-            gopherState->len = 0;
-        } else {
-            memcpy(line, pos, llen);
-        }
-        line[llen + 1] = '\0';
-        /* move input to next line */
-        pos = lpos;
-
-        /* at this point. We should have one line in buffer to process */
-
-        if (*line == '.') {
-            /* skip it */
-            memset(line, '\0', TEMP_BUF_SIZE);
-            continue;
-        }
-
-        switch (gopherState->conversion) {
-
-        case GopherStateData::HTML_INDEX_RESULT:
-
-        case GopherStateData::HTML_DIR: {
-            tline = line;
-            gtype = *tline;
-            ++tline;
-            name = tline;
-            selector = strchr(tline, TAB);
-
-            if (selector) {
-                *selector = '\0';
-                ++selector;
-                host = strchr(selector, TAB);
-
-                if (host) {
-                    *host = '\0';
-                    ++host;
-                    port = strchr(host, TAB);
-
-                    if (port) {
-                        char *junk;
-                        port[0] = ':';
-                        junk = strchr(host, TAB);
-
-                        if (junk)
-                            *junk++ = 0;    /* Chop port */
-                        else {
-                            junk = strchr(host, '\r');
-
-                            if (junk)
-                                *junk++ = 0;    /* Chop port */
-                            else {
-                                junk = strchr(host, '\n');
-
-                                if (junk)
-                                    *junk++ = 0;    /* Chop port */
-                            }
-                        }
-
-                        if ((port[1] == '0') && (!port[2]))
-                            port[0] = 0;    /* 0 means none */
-                    }
-
-                    /* escape a selector here */
-                    escaped_selector = xstrdup(rfc1738_escape_part(selector));
-
-                    switch (gtype) {
-
-                    case GOPHER_DIRECTORY:
-                        icon_url = mimeGetIconURL("internal-menu");
-                        break;
-
-                    case GOPHER_HTML:
-
-                    case GOPHER_FILE:
-                        icon_url = mimeGetIconURL("internal-text");
-                        break;
-
-                    case GOPHER_INDEX:
-
-                    case GOPHER_CSO:
-                        icon_url = mimeGetIconURL("internal-index");
-                        break;
-
-                    case GOPHER_IMAGE:
-
-                    case GOPHER_GIF:
-
-                    case GOPHER_PLUS_IMAGE:
-                        icon_url = mimeGetIconURL("internal-image");
-                        break;
-
-                    case GOPHER_SOUND:
-
-                    case GOPHER_PLUS_SOUND:
-                        icon_url = mimeGetIconURL("internal-sound");
-                        break;
-
-                    case GOPHER_PLUS_MOVIE:
-                        icon_url = mimeGetIconURL("internal-movie");
-                        break;
-
-                    case GOPHER_TELNET:
-
-                    case GOPHER_3270:
-                        icon_url = mimeGetIconURL("internal-telnet");
-                        break;
-
-                    case GOPHER_BIN:
-
-                    case GOPHER_MACBINHEX:
-
-                    case GOPHER_DOSBIN:
-
-                    case GOPHER_UUENCODED:
-                        icon_url = mimeGetIconURL("internal-binary");
-                        break;
-
-                    case GOPHER_INFO:
-                        icon_url = NULL;
-                        break;
-
-                    default:
-                        icon_url = mimeGetIconURL("internal-unknown");
-                        break;
-                    }
-
-                    if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) {
-                        if (strlen(escaped_selector) != 0)
-                            outbuf.appendf(" %s\n",
-                                           icon_url, escaped_selector, rfc1738_escape_part(host),
-                                           *port ? ":" : "", port, html_quote(name));
-                        else
-                            outbuf.appendf(" %s\n",
-                                           icon_url, rfc1738_escape_part(host), *port ? ":" : "",
-                                           port, html_quote(name));
-
-                    } else if (gtype == GOPHER_INFO) {
-                        outbuf.appendf("\t%s\n", html_quote(name));
-                    } else {
-                        if (strncmp(selector, "GET /", 5) == 0) {
-                            /* WWW link */
-                            outbuf.appendf(" %s\n",
-                                           icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name));
-                        } else if (gtype == GOPHER_WWW) {
-                            outbuf.appendf(" %s\n",
-                                           icon_url, rfc1738_escape_unescaped(selector), html_quote(name));
-                        } else {
-                            /* Standard link */
-                            outbuf.appendf(" %s\n",
-                                           icon_url, host, gtype, escaped_selector, html_quote(name));
-                        }
-                    }
-
-                    safe_free(escaped_selector);
-                } else {
-                    memset(line, '\0', TEMP_BUF_SIZE);
-                    continue;
-                }
-            } else {
-                memset(line, '\0', TEMP_BUF_SIZE);
-                continue;
-            }
-
-            break;
-            }           /* HTML_DIR, HTML_INDEX_RESULT */
-
-        case GopherStateData::HTML_CSO_RESULT: {
-            if (line[0] == '-') {
-                int code, recno;
-                char *s_code, *s_recno, *result;
-
-                s_code = strtok(line + 1, ":\n");
-                s_recno = strtok(NULL, ":\n");
-                result = strtok(NULL, "\n");
-
-                if (!result)
-                    break;
-
-                code = atoi(s_code);
-
-                recno = atoi(s_recno);
-
-                if (code != 200)
-                    break;
-
-                if (gopherState->cso_recno != recno) {
-                    outbuf.appendf("

Record# %d
%s

\n
", recno, html_quote(result));
-                    gopherState->cso_recno = recno;
-                } else {
-                    outbuf.appendf("%s\n", html_quote(result));
-                }
-
-                break;
-            } else {
-                int code;
-                char *s_code, *result;
-
-                s_code = strtok(line, ":");
-                result = strtok(NULL, "\n");
-
-                if (!result)
-                    break;
-
-                code = atoi(s_code);
-
-                switch (code) {
-
-                case 200: {
-                    /* OK */
-                    /* Do nothing here */
-                    break;
-                }
-
-                case 102:   /* Number of matches */
-
-                case 501:   /* No Match */
-
-                case 502: { /* Too Many Matches */
-                    /* Print the message the server returns */
-                    outbuf.appendf("

%s

\n
", html_quote(result));
-                    break;
-                }
-
-                }
-            }
-
-            }           /* HTML_CSO_RESULT */
-
-        default:
-            break;      /* do nothing */
-
-        }           /* switch */
-
-    }               /* while loop */
-
-    if (outbuf.length() > 0) {
-        entry->append(outbuf.rawContent(), outbuf.length());
-        /* now let start sending stuff to client */
-        entry->flush();
-    }
-
-    return;
-}
-
-static void
-gopherTimeout(const CommTimeoutCbParams &io)
-{
-    GopherStateData *gopherState = static_cast(io.data);
-    debugs(10, 4, HERE << io.conn << ": '" << gopherState->entry->url() << "'" );
-
-    gopherState->fwd->fail(new ErrorState(ERR_READ_TIMEOUT, Http::scGatewayTimeout, gopherState->fwd->request, gopherState->fwd->al));
-
-    if (Comm::IsConnOpen(io.conn))
-        io.conn->close();
-}
-
-/**
- * This will be called when data is ready to be read from fd.
- * Read until error or connection closed.
- */
-static void
-gopherReadReply(const Comm::ConnectionPointer &conn, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
-{
-    GopherStateData *gopherState = (GopherStateData *)data;
-    StoreEntry *entry = gopherState->entry;
-    int clen;
-    int bin;
-    size_t read_sz = BUFSIZ;
-#if USE_DELAY_POOLS
-    DelayId delayId = entry->mem_obj->mostBytesAllowed();
-#endif
-
-    /* Bail out early on Comm::ERR_CLOSING - close handlers will tidy up for us */
-
-    if (flag == Comm::ERR_CLOSING) {
-        return;
-    }
-
-    assert(buf == gopherState->replybuf);
-
-    // XXX: Should update delayId, statCounter, etc. before bailing
-    if (!entry->isAccepting()) {
-        debugs(10, 3, "terminating due to bad " << *entry);
-        // TODO: Do not abuse connection for triggering cleanup.
-        gopherState->serverConn->close();
-        return;
-    }
-
-#if USE_DELAY_POOLS
-    read_sz = delayId.bytesWanted(1, read_sz);
-#endif
-
-    /* leave one space for \0 in gopherToHTML */
-
-    if (flag == Comm::OK && len > 0) {
-#if USE_DELAY_POOLS
-        delayId.bytesIn(len);
-#endif
-
-        statCounter.server.all.kbytes_in += len;
-        statCounter.server.other.kbytes_in += len;
-    }
-
-    debugs(10, 5, HERE << conn << " read len=" << len);
-
-    if (flag == Comm::OK && len > 0) {
-        AsyncCall::Pointer nil;
-        commSetConnTimeout(conn, Config.Timeout.read, nil);
-        ++IOStats.Gopher.reads;
-
-        for (clen = len - 1, bin = 0; clen; ++bin)
-            clen >>= 1;
-
-        ++IOStats.Gopher.read_hist[bin];
-
-        HttpRequest *req = gopherState->fwd->request;
-        if (req->hier.bodyBytesRead < 0) {
-            req->hier.bodyBytesRead = 0;
-            // first bytes read, update Reply flags:
-            gopherState->reply_->sources |= Http::Message::srcGopher;
-        }
-
-        req->hier.bodyBytesRead += len;
-    }
-
-    if (flag != Comm::OK) {
-        debugs(50, DBG_IMPORTANT, MYNAME << "error reading: " << xstrerr(xerrno));
-
-        if (ignoreErrno(xerrno)) {
-            AsyncCall::Pointer call = commCbCall(5,4, "gopherReadReply",
-                                                 CommIoCbPtrFun(gopherReadReply, gopherState));
-            comm_read(conn, buf, read_sz, call);
-        } else {
-            const auto err = new ErrorState(ERR_READ_ERROR, Http::scInternalServerError, gopherState->fwd->request, gopherState->fwd->al);
-            err->xerrno = xerrno;
-            gopherState->fwd->fail(err);
-            gopherState->serverConn->close();
-        }
-    } else if (len == 0 && entry->isEmpty()) {
-        gopherState->fwd->fail(new ErrorState(ERR_ZERO_SIZE_OBJECT, Http::scServiceUnavailable, gopherState->fwd->request, gopherState->fwd->al));
-        gopherState->serverConn->close();
-    } else if (len == 0) {
-        /* Connection closed; retrieval done. */
-        /* flush the rest of data in temp buf if there is one. */
-
-        if (gopherState->conversion != GopherStateData::NORMAL)
-            gopherEndHTML(gopherState);
-
-        entry->timestampsSet();
-        entry->flush();
-
-        if (!gopherState->len && !gopherState->overflowed)
-            gopherState->fwd->markStoredReplyAsWhole("gopher EOF after receiving/storing some bytes");
-
-        gopherState->fwd->complete();
-        gopherState->serverConn->close();
-    } else {
-        if (gopherState->conversion != GopherStateData::NORMAL) {
-            gopherToHTML(gopherState, buf, len);
-        } else {
-            entry->append(buf, len);
-        }
-        AsyncCall::Pointer call = commCbCall(5,4, "gopherReadReply",
-                                             CommIoCbPtrFun(gopherReadReply, gopherState));
-        comm_read(conn, buf, read_sz, call);
-    }
-}
-
-/**
- * This will be called when request write is complete. Schedule read of reply.
- */
-static void
-gopherSendComplete(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag errflag, int xerrno, void *data)
-{
-    GopherStateData *gopherState = (GopherStateData *) data;
-    StoreEntry *entry = gopherState->entry;
-    debugs(10, 5, HERE << conn << " size: " << size << " errflag: " << errflag);
-
-    if (size > 0) {
-        fd_bytes(conn->fd, size, FD_WRITE);
-        statCounter.server.all.kbytes_out += size;
-        statCounter.server.other.kbytes_out += size;
-    }
-
-    if (!entry->isAccepting()) {
-        debugs(10, 3, "terminating due to bad " << *entry);
-        // TODO: Do not abuse connection for triggering cleanup.
-        gopherState->serverConn->close();
-        return;
-    }
-
-    if (errflag) {
-        const auto err = new ErrorState(ERR_WRITE_ERROR, Http::scServiceUnavailable, gopherState->fwd->request, gopherState->fwd->al);
-        err->xerrno = xerrno;
-        err->port = gopherState->fwd->request->url.port();
-        err->url = xstrdup(entry->url());
-        gopherState->fwd->fail(err);
-        gopherState->serverConn->close();
-        return;
-    }
-
-    /*
-     * OK. We successfully reach remote site.  Start MIME typing
-     * stuff.  Do it anyway even though request is not HTML type.
-     */
-    entry->buffer();
-
-    gopherMimeCreate(gopherState);
-
-    switch (gopherState->type_id) {
-
-    case GOPHER_DIRECTORY:
-        /* we got to convert it first */
-        gopherState->conversion = GopherStateData::HTML_DIR;
-        gopherState->HTML_header_added = 0;
-        break;
-
-    case GOPHER_INDEX:
-        /* we got to convert it first */
-        gopherState->conversion = GopherStateData::HTML_INDEX_RESULT;
-        gopherState->HTML_header_added = 0;
-        break;
-
-    case GOPHER_CSO:
-        /* we got to convert it first */
-        gopherState->conversion = GopherStateData::HTML_CSO_RESULT;
-        gopherState->cso_recno = 0;
-        gopherState->HTML_header_added = 0;
-        break;
-
-    default:
-        gopherState->conversion = GopherStateData::NORMAL;
-        entry->flush();
-    }
-
-    /* Schedule read reply. */
-    AsyncCall::Pointer call =  commCbCall(5,5, "gopherReadReply",
-                                          CommIoCbPtrFun(gopherReadReply, gopherState));
-    entry->delayAwareRead(conn, gopherState->replybuf, BUFSIZ, call);
-}
-
-/**
- * This will be called when connect completes. Write request.
- */
-static void
-gopherSendRequest(int, void *data)
-{
-    GopherStateData *gopherState = (GopherStateData *)data;
-    MemBuf mb;
-    mb.init();
-
-    if (gopherState->type_id == GOPHER_CSO) {
-        const char *t = strchr(gopherState->request, '?');
-
-        if (t)
-            ++t;        /* skip the ? */
-        else
-            t = "";
-
-        mb.appendf("query %s\r\nquit", t);
-    } else {
-        if (gopherState->type_id == GOPHER_INDEX) {
-            if (char *t = strchr(gopherState->request, '?'))
-                *t = '\t';
-        }
-        mb.append(gopherState->request, strlen(gopherState->request));
-    }
-    mb.append("\r\n", 2);
-
-    debugs(10, 5, gopherState->serverConn);
-    AsyncCall::Pointer call = commCbCall(5,5, "gopherSendComplete",
-                                         CommIoCbPtrFun(gopherSendComplete, gopherState));
-    Comm::Write(gopherState->serverConn, &mb, call);
-
-    if (!gopherState->entry->makePublic())
-        gopherState->entry->makePrivate(true);
-}
-
-void
-gopherStart(FwdState * fwd)
-{
-    GopherStateData *gopherState = new GopherStateData(fwd);
-
-    debugs(10, 3, gopherState->entry->url());
-
-    ++ statCounter.server.all.requests;
-
-    ++ statCounter.server.other.requests;
-
-    /* Parse url. */
-    gopher_request_parse(fwd->request,
-                         &gopherState->type_id, gopherState->request);
-
-    comm_add_close_handler(fwd->serverConnection()->fd, gopherStateFree, gopherState);
-
-    if (((gopherState->type_id == GOPHER_INDEX) || (gopherState->type_id == GOPHER_CSO))
-            && (strchr(gopherState->request, '?') == NULL)) {
-        /* Index URL without query word */
-        /* We have to generate search page back to client. No need for connection */
-        gopherMimeCreate(gopherState);
-
-        if (gopherState->type_id == GOPHER_INDEX) {
-            gopherState->conversion = GopherStateData::HTML_INDEX_PAGE;
-        } else {
-            if (gopherState->type_id == GOPHER_CSO) {
-                gopherState->conversion = GopherStateData::HTML_CSO_PAGE;
-            } else {
-                gopherState->conversion = GopherStateData::HTML_INDEX_PAGE;
-            }
-        }
-
-        gopherToHTML(gopherState, (char *) NULL, 0);
-        fwd->markStoredReplyAsWhole("gopher instant internal request satisfaction");
-        fwd->complete();
-        return;
-    }
-
-    // XXX: Sharing open Connection with FwdState that has its own handlers/etc.
-    gopherState->serverConn = fwd->serverConnection();
-    gopherSendRequest(fwd->serverConnection()->fd, gopherState);
-    AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "gopherTimeout",
-                                     CommTimeoutCbPtrFun(gopherTimeout, gopherState));
-    commSetConnTimeout(fwd->serverConnection(), Config.Timeout.read, timeoutCall);
-}
-
diff --git a/src/gopher.h b/src/gopher.h
deleted file mode 100644
index f63504b..0000000
--- a/src/gopher.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/* DEBUG: section 10    Gopher */
-
-#ifndef SQUID_GOPHER_H_
-#define SQUID_GOPHER_H_
-
-class FwdState;
-class HttpRequest;
-
-/**
- \defgroup ServerProtocolGopherAPI Server-Side Gopher API
- \ingroup ServerProtocol
- */
-
-/// \ingroup ServerProtocolGopherAPI
-void gopherStart(FwdState *);
-
-/// \ingroup ServerProtocolGopherAPI
-int gopherCachable(const HttpRequest *);
-
-#endif /* SQUID_GOPHER_H_ */
-
diff --git a/src/http/Message.h b/src/http/Message.h
index 1807023..92b5b1d 100644
--- a/src/http/Message.h
+++ b/src/http/Message.h
@@ -40,7 +40,6 @@ public:
         srcFtp = 1 << (16 + 1), ///< ftp_port or FTP server
         srcIcap = 1 << (16 + 2), ///< traditional ICAP service without encryption
         srcEcap = 1 << (16 + 3), ///< eCAP service that uses insecure libraries/daemons
-        srcGopher = 1 << (16 + 14), ///< Gopher server
         srcWhois = 1 << (16 + 15), ///< Whois server
         srcUnsafe = 0xFFFF0000,  ///< Unsafe sources mask
         srcSafe = 0x0000FFFF ///< Safe sources mask
diff --git a/src/mgr/IoAction.cc b/src/mgr/IoAction.cc
index 94a5c03..062d5e3 100644
--- a/src/mgr/IoAction.cc
+++ b/src/mgr/IoAction.cc
@@ -35,9 +35,6 @@ Mgr::IoActionData::operator += (const IoActionData& stats)
     ftp_reads += stats.ftp_reads;
     for (int i = 0; i < IoStats::histSize; ++i)
         ftp_read_hist[i] += stats.ftp_read_hist[i];
-    gopher_reads += stats.gopher_reads;
-    for (int i = 0; i < IoStats::histSize; ++i)
-        gopher_read_hist[i] += stats.gopher_read_hist[i];
 
     return *this;
 }
diff --git a/src/mgr/IoAction.h b/src/mgr/IoAction.h
index 7e9ad1a..dc4a3a5 100644
--- a/src/mgr/IoAction.h
+++ b/src/mgr/IoAction.h
@@ -27,10 +27,8 @@ public:
 public:
     double http_reads;
     double ftp_reads;
-    double gopher_reads;
     double http_read_hist[IoStats::histSize];
     double ftp_read_hist[IoStats::histSize];
-    double gopher_read_hist[IoStats::histSize];
 };
 
 /// implement aggregated 'io' action
diff --git a/src/squid.8.in b/src/squid.8.in
index 36bc0dd..472afcd 100644
--- a/src/squid.8.in
+++ b/src/squid.8.in
@@ -25,7 +25,7 @@ command\-line
 .PP
 .B squid
 is a high\-performance proxy caching server for web clients,
-supporting FTP, gopher, ICAP, ICP, HTCP and HTTP data objects.
+supporting FTP, ICAP, ICP, HTCP and HTTP data objects.
 Unlike traditional caching software, 
 Squid handles all requests in a single, non-blocking process.
 .PP
diff --git a/src/stat.cc b/src/stat.cc
index 6171077..3bc1f47 100644
--- a/src/stat.cc
+++ b/src/stat.cc
@@ -206,12 +206,6 @@ GetIoStats(Mgr::IoActionData& stats)
     for (i = 0; i < IoStats::histSize; ++i) {
         stats.ftp_read_hist[i] = IOStats.Ftp.read_hist[i];
     }
-
-    stats.gopher_reads = IOStats.Gopher.reads;
-
-    for (i = 0; i < IoStats::histSize; ++i) {
-        stats.gopher_read_hist[i] = IOStats.Gopher.read_hist[i];
-    }
 }
 
 void
@@ -244,19 +238,6 @@ DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry)
                           Math::doublePercent(stats.ftp_read_hist[i], stats.ftp_reads));
     }
 
-    storeAppendPrintf(sentry, "\n");
-    storeAppendPrintf(sentry, "Gopher I/O\n");
-    storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.gopher_reads);
-    storeAppendPrintf(sentry, "Read Histogram:\n");
-
-    for (i = 0; i < IoStats::histSize; ++i) {
-        storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n",
-                          i ? (1 << (i - 1)) + 1 : 1,
-                          1 << i,
-                          stats.gopher_read_hist[i],
-                          Math::doublePercent(stats.gopher_read_hist[i], stats.gopher_reads));
-    }
-
     storeAppendPrintf(sentry, "\n");
 }
 
diff --git a/src/tests/Stub.am b/src/tests/Stub.am
index 3972203..410f2e5 100644
--- a/src/tests/Stub.am
+++ b/src/tests/Stub.am
@@ -29,7 +29,6 @@ STUB_SOURCE = \
     tests/stub_external_acl.cc \
     tests/stub_fatal.cc \
     tests/stub_fd.cc \
-    tests/stub_gopher.cc \
     tests/stub_helper.cc \
     tests/stub_HelperChildConfig.cc \
     tests/stub_http.cc \
diff --git a/src/tests/stub_gopher.cc b/src/tests/stub_gopher.cc
deleted file mode 100644
index 2dc56b9..0000000
--- a/src/tests/stub_gopher.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-
-#define STUB_API "gopher.cc"
-#include "tests/STUB.h"
-
-#include "gopher.h"
-void gopherStart(FwdState *) STUB
-int gopherCachable(const HttpRequest *) STUB
-
diff --git a/test-suite/squidconf/regressions-3.4.0.1 b/test-suite/squidconf/regressions-3.4.0.1
index 853a848..59238c6 100644
--- a/test-suite/squidconf/regressions-3.4.0.1
+++ b/test-suite/squidconf/regressions-3.4.0.1
@@ -44,6 +44,5 @@ refresh_pattern -i \.(gif|png|jpg|jpeg|ico)$ 40320 75% 86400
 refresh_pattern -i \.(iso|avi|wav|mp3|mpeg|swf|flv|x-flv)$ 1440 40% 40320
 
 refresh_pattern ^ftp:           1440    20%     10080
-refresh_pattern ^gopher:        1440    0%      1440
 refresh_pattern -i (/cgi-bin/|\?)       0       0%      0
 refresh_pattern .       0       20%     4320
diff --git a/src/Makefile.in b/src/Makefile.in
index 6f4a7b7..57d0c52 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -312,7 +312,7 @@ am__squid_SOURCES_DIST = AclRegs.cc AuthReg.cc BandwidthBucket.cc \
 	defines.h dlink.cc dlink.h enums.h errorpage.cc errorpage.h \
 	event.cc event.h external_acl.cc fatal.cc fatal.h fd.cc fd.h \
 	fde.cc fde.h filemap.cc fqdncache.cc fqdncache.h fs_io.cc \
-	fs_io.h globals.h gopher.cc gopher.h helper.cc helper.h \
+	fs_io.h globals.h helper.cc helper.h \
 	hier_code.h http.cc http.h icp_opcode.h icp_v2.cc icp_v3.cc \
 	int.cc int.h internal.cc internal.h ipcache.cc ipcache.h \
 	lookup_t.h main.cc mem_node.cc mem_node.h mime.cc mime.h \
@@ -392,7 +392,7 @@ am_squid_OBJECTS = $(am__objects_1) $(am__objects_3) $(am__objects_4) \
 	client_side_request.$(OBJEXT) debug.$(OBJEXT) dlink.$(OBJEXT) \
 	errorpage.$(OBJEXT) event.$(OBJEXT) external_acl.$(OBJEXT) \
 	fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \
-	fqdncache.$(OBJEXT) fs_io.$(OBJEXT) gopher.$(OBJEXT) \
+	fqdncache.$(OBJEXT) fs_io.$(OBJEXT) \
 	helper.$(OBJEXT) http.$(OBJEXT) icp_v2.$(OBJEXT) \
 	icp_v3.$(OBJEXT) int.$(OBJEXT) internal.$(OBJEXT) \
 	ipcache.$(OBJEXT) main.$(OBJEXT) mem_node.$(OBJEXT) \
@@ -552,7 +552,7 @@ am__tests_testCacheManager_SOURCES_DIST = BandwidthBucket.cc \
 	debug.cc dlink.cc dlink.h errorpage.cc event.cc \
 	external_acl.cc tests/stub_fatal.cc fatal.h fd.cc fd.h fde.cc \
 	filemap.cc fqdncache.cc fqdncache.h fs_io.cc fs_io.h \
-	tests/stub_gopher.cc gopher.h helper.cc hier_code.h http.cc \
+	helper.cc hier_code.h http.cc \
 	icp_v2.cc icp_v3.cc int.cc int.h internal.cc internal.h \
 	tests/stub_ipc_Forwarder.cc ipcache.cc tests/stub_libauth.cc \
 	tests/stub_libauth_acls.cc tests/stub_libdiskio.cc \
@@ -607,7 +607,7 @@ am_tests_testCacheManager_OBJECTS = $(am__objects_3) $(am__objects_4) \
 	errorpage.$(OBJEXT) event.$(OBJEXT) external_acl.$(OBJEXT) \
 	tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \
 	filemap.$(OBJEXT) fqdncache.$(OBJEXT) fs_io.$(OBJEXT) \
-	tests/stub_gopher.$(OBJEXT) helper.$(OBJEXT) http.$(OBJEXT) \
+	helper.$(OBJEXT) http.$(OBJEXT) \
 	icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) int.$(OBJEXT) \
 	internal.$(OBJEXT) tests/stub_ipc_Forwarder.$(OBJEXT) \
 	ipcache.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
@@ -869,7 +869,7 @@ am__tests_testEvent_SOURCES_DIST = BandwidthBucket.cc \
 	debug.cc dlink.cc dlink.h errorpage.cc event.cc \
 	external_acl.cc tests/stub_fatal.cc fatal.h fd.cc fd.h fde.cc \
 	filemap.cc fqdncache.cc fqdncache.h fs_io.cc fs_io.h \
-	tests/stub_gopher.cc gopher.h helper.cc hier_code.h http.cc \
+	helper.cc hier_code.h http.cc \
 	icp_v2.cc icp_v3.cc int.cc int.h internal.cc internal.h \
 	tests/stub_ipc_Forwarder.cc ipcache.cc tests/stub_libauth.cc \
 	tests/stub_libauth_acls.cc tests/stub_libdiskio.cc \
@@ -925,7 +925,7 @@ am_tests_testEvent_OBJECTS = $(am__objects_3) $(am__objects_4) \
 	event.$(OBJEXT) external_acl.$(OBJEXT) \
 	tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \
 	filemap.$(OBJEXT) fqdncache.$(OBJEXT) fs_io.$(OBJEXT) \
-	tests/stub_gopher.$(OBJEXT) helper.$(OBJEXT) http.$(OBJEXT) \
+	helper.$(OBJEXT) http.$(OBJEXT) \
 	icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) int.$(OBJEXT) \
 	internal.$(OBJEXT) tests/stub_ipc_Forwarder.$(OBJEXT) \
 	ipcache.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
@@ -1013,7 +1013,7 @@ am__tests_testEventLoop_SOURCES_DIST = BandwidthBucket.cc \
 	debug.cc dlink.cc dlink.h errorpage.cc event.cc \
 	external_acl.cc tests/stub_fatal.cc fatal.h fd.cc fd.h fde.cc \
 	filemap.cc fqdncache.cc fqdncache.h fs_io.cc fs_io.h \
-	tests/stub_gopher.cc gopher.h helper.cc hier_code.h http.cc \
+	helper.cc hier_code.h http.cc \
 	icp_v2.cc icp_v3.cc int.cc int.h internal.cc internal.h \
 	tests/stub_ipc_Forwarder.cc ipcache.cc tests/stub_libauth.cc \
 	tests/stub_libauth_acls.cc tests/stub_libdiskio.cc \
@@ -1068,7 +1068,7 @@ am_tests_testEventLoop_OBJECTS = $(am__objects_3) $(am__objects_4) \
 	event.$(OBJEXT) external_acl.$(OBJEXT) \
 	tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \
 	filemap.$(OBJEXT) fqdncache.$(OBJEXT) fs_io.$(OBJEXT) \
-	tests/stub_gopher.$(OBJEXT) helper.$(OBJEXT) http.$(OBJEXT) \
+	helper.$(OBJEXT) http.$(OBJEXT) \
 	icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) int.$(OBJEXT) \
 	internal.$(OBJEXT) tests/stub_ipc_Forwarder.$(OBJEXT) \
 	ipcache.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
@@ -1226,8 +1226,8 @@ am__tests_testHttpRequest_SOURCES_DIST = BandwidthBucket.cc \
 	client_side.h client_side_reply.cc client_side_request.cc \
 	debug.cc dlink.cc dlink.h errorpage.cc event.cc \
 	external_acl.cc tests/stub_fatal.cc fatal.h fd.cc fd.h fde.cc \
-	fqdncache.cc fqdncache.h fs_io.cc fs_io.h tests/stub_gopher.cc \
-	gopher.h helper.cc hier_code.h http.cc icp_v2.cc icp_v3.cc \
+	fqdncache.cc fqdncache.h fs_io.cc fs_io.h \
+	helper.cc hier_code.h http.cc icp_v2.cc icp_v3.cc \
 	int.cc int.h internal.cc internal.h \
 	tests/stub_ipc_Forwarder.cc ipcache.cc tests/stub_libauth.cc \
 	tests/stub_libauth_acls.cc tests/stub_libdiskio.cc \
@@ -1283,7 +1283,7 @@ am_tests_testHttpRequest_OBJECTS = $(am__objects_3) $(am__objects_4) \
 	event.$(OBJEXT) external_acl.$(OBJEXT) \
 	tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \
 	fqdncache.$(OBJEXT) fs_io.$(OBJEXT) \
-	tests/stub_gopher.$(OBJEXT) helper.$(OBJEXT) http.$(OBJEXT) \
+	helper.$(OBJEXT) http.$(OBJEXT) \
 	icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) int.$(OBJEXT) \
 	internal.$(OBJEXT) tests/stub_ipc_Forwarder.$(OBJEXT) \
 	ipcache.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
@@ -1973,8 +1973,8 @@ am__tests_test_http_range_SOURCES_DIST = BandwidthBucket.cc \
 	client_side_reply.cc client_side_request.cc debug.cc dlink.cc \
 	dlink.h errorpage.cc event.cc tests/stub_external_acl.cc \
 	tests/stub_fatal.cc fatal.h fd.cc fd.h fde.cc filemap.cc \
-	fqdncache.cc fqdncache.h fs_io.cc fs_io.h tests/stub_gopher.cc \
-	gopher.h helper.cc hier_code.h http.cc icp_v2.cc icp_v3.cc \
+	fqdncache.cc fqdncache.h fs_io.cc fs_io.h \
+	helper.cc hier_code.h http.cc icp_v2.cc icp_v3.cc \
 	int.cc int.h internal.cc internal.h \
 	tests/stub_ipc_Forwarder.cc ipcache.cc tests/stub_libauth.cc \
 	tests/stub_libdiskio.cc tests/stub_liberror.cc \
@@ -2030,7 +2030,7 @@ am_tests_test_http_range_OBJECTS = $(am__objects_3) $(am__objects_4) \
 	tests/stub_external_acl.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \
 	fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \
 	fqdncache.$(OBJEXT) fs_io.$(OBJEXT) \
-	tests/stub_gopher.$(OBJEXT) helper.$(OBJEXT) http.$(OBJEXT) \
+	helper.$(OBJEXT) http.$(OBJEXT) \
 	icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) int.$(OBJEXT) \
 	internal.$(OBJEXT) tests/stub_ipc_Forwarder.$(OBJEXT) \
 	ipcache.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
@@ -2166,7 +2166,7 @@ am__depfiles_remade = ./$(DEPDIR)/AccessLogEntry.Po \
 	./$(DEPDIR)/external_acl.Po ./$(DEPDIR)/fatal.Po \
 	./$(DEPDIR)/fd.Po ./$(DEPDIR)/fde.Po ./$(DEPDIR)/filemap.Po \
 	./$(DEPDIR)/fqdncache.Po ./$(DEPDIR)/fs_io.Po \
-	./$(DEPDIR)/globals.Po ./$(DEPDIR)/gopher.Po \
+	./$(DEPDIR)/globals.Po \
 	./$(DEPDIR)/helper.Po ./$(DEPDIR)/hier_code.Po \
 	./$(DEPDIR)/htcp.Po ./$(DEPDIR)/http.Po \
 	./$(DEPDIR)/icp_opcode.Po ./$(DEPDIR)/icp_v2.Po \
@@ -2227,7 +2227,7 @@ am__depfiles_remade = ./$(DEPDIR)/AccessLogEntry.Po \
 	tests/$(DEPDIR)/stub_event.Po \
 	tests/$(DEPDIR)/stub_external_acl.Po \
 	tests/$(DEPDIR)/stub_fatal.Po tests/$(DEPDIR)/stub_fd.Po \
-	tests/$(DEPDIR)/stub_gopher.Po tests/$(DEPDIR)/stub_helper.Po \
+	tests/$(DEPDIR)/stub_helper.Po \
 	tests/$(DEPDIR)/stub_http.Po tests/$(DEPDIR)/stub_icp.Po \
 	tests/$(DEPDIR)/stub_internal.Po tests/$(DEPDIR)/stub_ipc.Po \
 	tests/$(DEPDIR)/stub_ipc_Forwarder.Po \
@@ -3131,7 +3131,7 @@ squid_SOURCES = $(ACL_REGISTRATION_SOURCES) $(DELAY_POOL_SOURCE) \
 	defines.h dlink.cc dlink.h enums.h errorpage.cc errorpage.h \
 	event.cc event.h external_acl.cc fatal.cc fatal.h fd.cc fd.h \
 	fde.cc fde.h filemap.cc fqdncache.cc fqdncache.h fs_io.cc \
-	fs_io.h globals.h gopher.cc gopher.h helper.cc helper.h \
+	fs_io.h globals.h helper.cc helper.h \
 	hier_code.h http.cc http.h icp_opcode.h icp_v2.cc icp_v3.cc \
 	int.cc int.h internal.cc internal.h ipcache.cc ipcache.h \
 	lookup_t.h main.cc mem_node.cc mem_node.h mime.cc mime.h \
@@ -3326,7 +3326,6 @@ STUB_SOURCE = \
     tests/stub_external_acl.cc \
     tests/stub_fatal.cc \
     tests/stub_fd.cc \
-    tests/stub_gopher.cc \
     tests/stub_helper.cc \
     tests/stub_HelperChildConfig.cc \
     tests/stub_http.cc \
@@ -4469,8 +4468,6 @@ tests_test_http_range_SOURCES = \
 	fqdncache.h \
 	fs_io.cc \
 	fs_io.h \
-	tests/stub_gopher.cc \
-	gopher.h \
 	helper.cc \
 	hier_code.h \
 	http.cc \
@@ -4862,8 +4859,6 @@ tests_testHttpRequest_SOURCES = \
 	fqdncache.h \
 	fs_io.cc \
 	fs_io.h \
-	tests/stub_gopher.cc \
-	gopher.h \
 	helper.cc \
 	hier_code.h \
 	http.cc \
@@ -5166,8 +5161,6 @@ tests_testCacheManager_SOURCES = \
 	fqdncache.h \
 	fs_io.cc \
 	fs_io.h \
-	tests/stub_gopher.cc \
-	gopher.h \
 	helper.cc \
 	hier_code.h \
 	http.cc \
@@ -5487,8 +5480,6 @@ tests_testEvent_SOURCES = \
 	fqdncache.h \
 	fs_io.cc \
 	fs_io.h \
-	tests/stub_gopher.cc \
-	gopher.h \
 	helper.cc \
 	hier_code.h \
 	http.cc \
@@ -5729,8 +5720,6 @@ tests_testEventLoop_SOURCES = \
 	fqdncache.h \
 	fs_io.cc \
 	fs_io.h \
-	tests/stub_gopher.cc \
-	gopher.h \
 	helper.cc \
 	hier_code.h \
 	http.cc \
@@ -6147,8 +6136,6 @@ tests/stub_carp.$(OBJEXT): tests/$(am__dirstamp) \
 	tests/$(DEPDIR)/$(am__dirstamp)
 tests/stub_client_db.$(OBJEXT): tests/$(am__dirstamp) \
 	tests/$(DEPDIR)/$(am__dirstamp)
-tests/stub_gopher.$(OBJEXT): tests/$(am__dirstamp) \
-	tests/$(DEPDIR)/$(am__dirstamp)
 tests/stub_ipc_Forwarder.$(OBJEXT): tests/$(am__dirstamp) \
 	tests/$(DEPDIR)/$(am__dirstamp)
 tests/stub_libauth_acls.$(OBJEXT): tests/$(am__dirstamp) \
@@ -6560,7 +6547,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fqdncache.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_io.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globals.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gopher.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hier_code.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htcp.Po@am__quote@ # am--include-marker
@@ -6657,7 +6643,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_external_acl.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_fatal.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_fd.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_gopher.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_helper.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_http.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_icp.Po@am__quote@ # am--include-marker
@@ -7555,7 +7540,6 @@ distclean: distclean-recursive
 	-rm -f ./$(DEPDIR)/fqdncache.Po
 	-rm -f ./$(DEPDIR)/fs_io.Po
 	-rm -f ./$(DEPDIR)/globals.Po
-	-rm -f ./$(DEPDIR)/gopher.Po
 	-rm -f ./$(DEPDIR)/helper.Po
 	-rm -f ./$(DEPDIR)/hier_code.Po
 	-rm -f ./$(DEPDIR)/htcp.Po
@@ -7652,7 +7636,6 @@ distclean: distclean-recursive
 	-rm -f tests/$(DEPDIR)/stub_external_acl.Po
 	-rm -f tests/$(DEPDIR)/stub_fatal.Po
 	-rm -f tests/$(DEPDIR)/stub_fd.Po
-	-rm -f tests/$(DEPDIR)/stub_gopher.Po
 	-rm -f tests/$(DEPDIR)/stub_helper.Po
 	-rm -f tests/$(DEPDIR)/stub_http.Po
 	-rm -f tests/$(DEPDIR)/stub_icp.Po
@@ -7887,7 +7870,6 @@ maintainer-clean: maintainer-clean-recursive
 	-rm -f ./$(DEPDIR)/fqdncache.Po
 	-rm -f ./$(DEPDIR)/fs_io.Po
 	-rm -f ./$(DEPDIR)/globals.Po
-	-rm -f ./$(DEPDIR)/gopher.Po
 	-rm -f ./$(DEPDIR)/helper.Po
 	-rm -f ./$(DEPDIR)/hier_code.Po
 	-rm -f ./$(DEPDIR)/htcp.Po
@@ -7984,7 +7966,6 @@ maintainer-clean: maintainer-clean-recursive
 	-rm -f tests/$(DEPDIR)/stub_external_acl.Po
 	-rm -f tests/$(DEPDIR)/stub_fatal.Po
 	-rm -f tests/$(DEPDIR)/stub_fd.Po
-	-rm -f tests/$(DEPDIR)/stub_gopher.Po
 	-rm -f tests/$(DEPDIR)/stub_helper.Po
 	-rm -f tests/$(DEPDIR)/stub_http.Po
 	-rm -f tests/$(DEPDIR)/stub_icp.Po