From b5d3c5c00b98563bc60a5a53d1e09dd239f78927 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Mon, 8 Jan 2024 07:36:06 +0000 Subject: [PATCH] import OL squid-4.15-7.module+el8.9.0+90111+615ac445.5 --- SOURCES/squid-4.15-CVE-2023-46724.patch | 38 + SOURCES/squid-4.15-CVE-2023-46728.patch | 3381 +++++++++++++++++++++++ SOURCES/squid-4.15-CVE-2023-49285.patch | 38 + SOURCES/squid-4.15-CVE-2023-49286.patch | 88 + SPECS/squid.spec | 16 +- 5 files changed, 3560 insertions(+), 1 deletion(-) create mode 100644 SOURCES/squid-4.15-CVE-2023-46724.patch create mode 100644 SOURCES/squid-4.15-CVE-2023-46728.patch create mode 100644 SOURCES/squid-4.15-CVE-2023-49285.patch create mode 100644 SOURCES/squid-4.15-CVE-2023-49286.patch diff --git a/SOURCES/squid-4.15-CVE-2023-46724.patch b/SOURCES/squid-4.15-CVE-2023-46724.patch new file mode 100644 index 0000000..41c30aa --- /dev/null +++ b/SOURCES/squid-4.15-CVE-2023-46724.patch @@ -0,0 +1,38 @@ +From 792ef23e6e1c05780fe17f733859eef6eb8c8be3 Mon Sep 17 00:00:00 2001 +From: Andreas Weigel +Date: Wed, 18 Oct 2023 04:14:31 +0000 +Subject: [PATCH] Fix validation of certificates with CN=* (#1523) + +The bug was discovered and detailed by Joshua Rogers at +https://megamansec.github.io/Squid-Security-Audit/ +where it was filed as "Buffer UnderRead in SSL CN Parsing". +--- + src/anyp/Uri.cc | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/anyp/Uri.cc b/src/anyp/Uri.cc +index 77b6f0c92..a6a5d5d9e 100644 +--- a/src/anyp/Uri.cc ++++ b/src/anyp/Uri.cc +@@ -173,6 +173,10 @@ urlInitialize(void) + assert(0 == matchDomainName("*.foo.com", ".foo.com", mdnHonorWildcards)); + assert(0 != matchDomainName("*.foo.com", "foo.com", mdnHonorWildcards)); + ++ assert(0 != matchDomainName("foo.com", "")); ++ assert(0 != matchDomainName("foo.com", "", mdnHonorWildcards)); ++ assert(0 != matchDomainName("foo.com", "", mdnRejectSubsubDomains)); ++ + /* more cases? */ + } + +@@ -756,6 +760,8 @@ matchDomainName(const char *h, const char *d, MatchDomainNameFlags flags) + return -1; + + dl = strlen(d); ++ if (dl == 0) ++ return 1; + + /* + * Start at the ends of the two strings and work towards the +-- +2.25.1 diff --git a/SOURCES/squid-4.15-CVE-2023-46728.patch b/SOURCES/squid-4.15-CVE-2023-46728.patch new file mode 100644 index 0000000..bb720b0 --- /dev/null +++ b/SOURCES/squid-4.15-CVE-2023-46728.patch @@ -0,0 +1,3381 @@ +From 6ea12e8fb590ac6959e9356a81aa3370576568c3 Mon Sep 17 00:00:00 2001 +From: Alex Rousskov +Date: Tue, 26 Jul 2022 15:05:54 +0000 +Subject: [PATCH] Remove support for Gopher protocol (#1092) + +Gopher code quality remains too low for production use in most +environments. The code is a persistent source of vulnerabilities and +fixing it requires significant effort. We should not be spending scarce +Project resources on improving that code, especially given the lack of +strong demand for Gopher support. + +With this change, Gopher requests will be handled like any other request +with an unknown (to Squid) protocol. For example, HTTP requests with +Gopher URI scheme result in ERR_UNSUP_REQ. + +Default Squid configuration still considers TCP port 70 "safe". The +corresponding Safe_ports ACL rule has not been removed for consistency +sake: We consider WAIS port safe even though Squid refuses to forward +WAIS requests: + + acl Safe_ports port 70 # gopher + acl Safe_ports port 210 # wais + +Back port upstream patch +Signed-Off-By: Tianyue.lan@oracle.com +--- + doc/debug-sections.txt | 1 - + errors/af/ERR_UNSUP_REQ | 2 +- + errors/ar/ERR_UNSUP_REQ | 2 +- + errors/az/ERR_UNSUP_REQ | 2 +- + errors/bg/ERR_UNSUP_REQ | 2 +- + errors/ca/ERR_UNSUP_REQ | 2 +- + errors/cs/ERR_UNSUP_REQ | 2 +- + errors/da/ERR_UNSUP_REQ | 2 +- + errors/de/ERR_UNSUP_REQ | 2 +- + errors/el/ERR_UNSUP_REQ | 2 +- + errors/en/ERR_UNSUP_REQ | 2 +- + errors/errorpage.css | 2 +- + errors/es/ERR_UNSUP_REQ | 2 +- + errors/et/ERR_UNSUP_REQ | 2 +- + errors/fa/ERR_UNSUP_REQ | 2 +- + errors/fi/ERR_UNSUP_REQ | 2 +- + errors/fr/ERR_UNSUP_REQ | 2 +- + errors/he/ERR_UNSUP_REQ | 2 +- + errors/hu/ERR_UNSUP_REQ | 2 +- + errors/hy/ERR_UNSUP_REQ | 2 +- + errors/id/ERR_UNSUP_REQ | 2 +- + errors/it/ERR_UNSUP_REQ | 2 +- + errors/ja/ERR_UNSUP_REQ | 2 +- + errors/ka/ERR_UNSUP_REQ | 2 +- + errors/ko/ERR_UNSUP_REQ | 2 +- + errors/lt/ERR_UNSUP_REQ | 2 +- + errors/lv/ERR_UNSUP_REQ | 2 +- + errors/ms/ERR_UNSUP_REQ | 2 +- + errors/nl/ERR_UNSUP_REQ | 2 +- + errors/oc/ERR_UNSUP_REQ | 2 +- + errors/pl/ERR_UNSUP_REQ | 2 +- + errors/pt-br/ERR_UNSUP_REQ | 2 +- + errors/pt/ERR_UNSUP_REQ | 2 +- + errors/ro/ERR_UNSUP_REQ | 2 +- + errors/ru/ERR_UNSUP_REQ | 2 +- + errors/sk/ERR_UNSUP_REQ | 2 +- + errors/sl/ERR_UNSUP_REQ | 2 +- + errors/sr-cyrl/ERR_UNSUP_REQ | 2 +- + errors/sr-latn/ERR_UNSUP_REQ | 2 +- + errors/sv/ERR_UNSUP_REQ | 2 +- + errors/templates/ERR_UNSUP_REQ | 2 +- + errors/th/ERR_UNSUP_REQ | 2 +- + errors/tr/ERR_UNSUP_REQ | 2 +- + errors/uk/ERR_UNSUP_REQ | 2 +- + errors/uz/ERR_UNSUP_REQ | 2 +- + errors/vi/ERR_UNSUP_REQ | 2 +- + errors/zh-hans/ERR_UNSUP_REQ | 2 +- + errors/zh-hant/ERR_UNSUP_REQ | 2 +- + src/FwdState.cc | 5 - + src/HttpMsg.h | 1 - + src/HttpRequest.cc | 6 - + src/IoStats.h | 2 +- + src/Makefile.am | 14 - + src/Makefile.in | 53 +- + src/adaptation/ecap/Host.cc | 1 - + src/adaptation/ecap/MessageRep.cc | 2 - + src/anyp/ProtocolType.cc | 1 - + src/anyp/ProtocolType.h | 1 - + src/anyp/Uri.cc | 2 - + src/anyp/UriScheme.cc | 3 - + src/cf.data.pre | 6 +- + src/cf.data.pre.config | 6 +- + src/client_side_request.cc | 4 - + src/err_type.h | 2 +- + src/gopher.cc | 977 ---------------------- + src/gopher.cc.CVE-2021-46784 | 982 ----------------------- + src/gopher.h | 29 - + src/mgr/IoAction.cc | 3 - + src/mgr/IoAction.h | 2 - + src/squid.8.in | 2 +- + src/stat.cc | 17 - + test-suite/squidconf/regressions-3.4.0.1 | 1 - + 72 files changed, 73 insertions(+), 2144 deletions(-) + delete mode 100644 src/gopher.cc + delete mode 100644 src/gopher.cc.CVE-2021-46784 + delete mode 100644 src/gopher.h + +diff --git a/doc/debug-sections.txt b/doc/debug-sections.txt +index 8b8b25f..50bd122 100644 +--- a/doc/debug-sections.txt ++++ b/doc/debug-sections.txt +@@ -27,7 +27,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/af/ERR_UNSUP_REQ b/errors/af/ERR_UNSUP_REQ +index c8c3152..d0895e2 100644 +--- a/errors/af/ERR_UNSUP_REQ ++++ b/errors/af/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Niegesteunde versoekmetode en -protokol

+ + +-

Squid ondersteun nie alle navraagmetodes vir alle toegangsprotokolle nie. Mens kan by voorbeeld nie 'n Gopher-navraag POST nie.

++

Squid ondersteun nie alle navraagmetodes vir alle toegangsprotokolle nie.

+ +

Die kasbediener se administrateur is %w.

+
+diff --git a/errors/ar/ERR_UNSUP_REQ b/errors/ar/ERR_UNSUP_REQ +index 909722f..dc8bceb 100644 +--- a/errors/ar/ERR_UNSUP_REQ ++++ b/errors/ar/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/az/ERR_UNSUP_REQ b/errors/az/ERR_UNSUP_REQ +index 50207d8..a1fba06 100644 +--- a/errors/az/ERR_UNSUP_REQ ++++ b/errors/az/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Dəstəklənməyən sorğu metodu və protokol

+ + +-

Squid bütün sorğu metodları və bütün protokollardəstəkləmir. Məsələn, Gopher protokolu üzrə siz POST sorğu metodunu yerinə yetirə bilməzsiniz.

++

Squid bütün sorğu metodları və bütün protokollardəstəkləmir.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/bg/ERR_UNSUP_REQ b/errors/bg/ERR_UNSUP_REQ +index e9130f9..6ff57a3 100644 +--- a/errors/bg/ERR_UNSUP_REQ ++++ b/errors/bg/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Сървърът не поддържа метода и/или протокола, посочен в заявката

+ + +-

Кеш сървърът не поддържа всички методи на заявка за всички протоколи. Например, не можете да заявите метод POST за протокол Gopher.

++

Кеш сървърът не поддържа всички методи на заявка за всички протоколи.

+ +

Вашият кеш администратор е %w.

+
+diff --git a/errors/ca/ERR_UNSUP_REQ b/errors/ca/ERR_UNSUP_REQ +index fe4433b..a62cf03 100644 +--- a/errors/ca/ERR_UNSUP_REQ ++++ b/errors/ca/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Mètode i protocol no admesos

+ + +-

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.

+ +

L'administrador d'aquesta cache és %w.

+
+diff --git a/errors/cs/ERR_UNSUP_REQ b/errors/cs/ERR_UNSUP_REQ +index cb955f9..42aeb7e 100644 +--- a/errors/cs/ERR_UNSUP_REQ ++++ b/errors/cs/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Unsupported Request Method and Protocol

+ + +-

Squid nepodporuje všechny typy metod u všech protokolů. Např. není možno použit metodu POST u služby GOPHER.

++

Squid nepodporuje všechny typy metod u všech protokolů.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/da/ERR_UNSUP_REQ b/errors/da/ERR_UNSUP_REQ +index f41d696..0d5d09a 100644 +--- a/errors/da/ERR_UNSUP_REQ ++++ b/errors/da/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Uunderstøttet Forespørgsels Metode og Protokol

+ + +-

Proxy'en Squid understøtter ikke alle forespørgselsmetoder for alle adgangs protokoller. For eksempel kan du ikke POST en Gopher forespørgsel.

++

Proxy'en Squid understøtter ikke alle forespørgselsmetoder for alle adgangs protokoller.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/de/ERR_UNSUP_REQ b/errors/de/ERR_UNSUP_REQ +index f106207..614e675 100644 +--- a/errors/de/ERR_UNSUP_REQ ++++ b/errors/de/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Anfragemethode und Protokoll nicht unterstützt

+ + +-

Squid unterstützt nicht alle Anfragemethoden für alle Protokolle. Sie können zum Beispiel keine POST Anfrage über das Gopher Protokoll senden.

++

Squid unterstützt nicht alle Anfragemethoden für alle Protokolle.

+ +

Ihr Cache Administrator ist %w.

+
+diff --git a/errors/el/ERR_UNSUP_REQ b/errors/el/ERR_UNSUP_REQ +index 0c232a5..5d092a7 100644 +--- a/errors/el/ERR_UNSUP_REQ ++++ b/errors/el/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Μη υποστηριζόμενη μέθοδος αίτησης και πρωτόκολλο

+ + +-

Το Squid δεν υποστηρίζει όλες τις μεθόδους αιτήσεων για όλα τα πρωτόκολλα πρόσβασης. Για παράδειγμα, το POST για Gopher δεν υποστηρίζεται.

++

Το Squid δεν υποστηρίζει όλες τις μεθόδους αιτήσεων για όλα τα πρωτόκολλα πρόσβασης.

+ +

Ο διαχειριστής του μεσολαβητή σας είναι ο %w.

+
+diff --git a/errors/en/ERR_UNSUP_REQ b/errors/en/ERR_UNSUP_REQ +index 352399d..e208043 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 38ba434..facee93 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/es/ERR_UNSUP_REQ b/errors/es/ERR_UNSUP_REQ +index eb1e86e..fc1a63f 100644 +--- a/errors/es/ERR_UNSUP_REQ ++++ b/errors/es/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Método de la petición y protocolo no soportados.

+ + +-

Squid no admite todos los métodos para todos los protocolos de acceso. Por ejemplo, no se puede hacer un POST a un servidor Gopher.

++

Squid no admite todos los métodos para todos los protocolos de acceso.

+ +

Su administrador del caché es %w.

+
+diff --git a/errors/et/ERR_UNSUP_REQ b/errors/et/ERR_UNSUP_REQ +index 5488e41..cf6ec2a 100644 +--- a/errors/et/ERR_UNSUP_REQ ++++ b/errors/et/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Tundmatu päringu meetod ja protokoll

+ + +-

Squid ei toeta kõiki päringu meetodeid kõikide protokollidega. Näiteks, te ei saa teha POST operatsiooni Gopher päringus.

++

Squid ei toeta kõiki päringu meetodeid kõikide protokollidega.

+ +

Teie teenusepakkuja aadress on %w.

+
+diff --git a/errors/fa/ERR_UNSUP_REQ b/errors/fa/ERR_UNSUP_REQ +index 065da44..9940bdc 100644 +--- a/errors/fa/ERR_UNSUP_REQ ++++ b/errors/fa/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

روش پشتیبانی‌نشده درخواست و قرارداد

+ + +-

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/fi/ERR_UNSUP_REQ b/errors/fi/ERR_UNSUP_REQ +index 6a99e60..e06ec69 100644 +--- a/errors/fi/ERR_UNSUP_REQ ++++ b/errors/fi/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Hakupyynnon tyyppi ja yhteyskäytäntö ei tuettu

+ + +-

Squid ei tue kaikkia hakupyynnon tyyppejä kaikilla protokollilla. Et voi esimerkiksi käyttää POST-pyyntöä gopherilla.

++

Squid ei tue kaikkia hakupyynnon tyyppejä kaikilla protokollilla.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/fr/ERR_UNSUP_REQ b/errors/fr/ERR_UNSUP_REQ +index 9bccd19..ddb6b85 100644 +--- a/errors/fr/ERR_UNSUP_REQ ++++ b/errors/fr/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

La méthode de requête et le protocole ne sont pas pris en charge.

+ + +-

Squid ne prend pas en charge tous les types de requêtes par rapport à tous les protocoles d'accès. Vous ne pouvez pas par exemple utiliser une requête POST avec le protocole Gopher.

++

Squid ne prend pas en charge tous les types de requêtes par rapport à tous les protocoles d'accès.

+ +

Votre administrateur proxy est %w.

+
+diff --git a/errors/he/ERR_UNSUP_REQ b/errors/he/ERR_UNSUP_REQ +index eaff6f3..8daee1a 100644 +--- a/errors/he/ERR_UNSUP_REQ ++++ b/errors/he/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

שיטת בקשה ופרוטוקול לא נתמכים

+ + +-

שרת ה Squid אינו תומך בכל שיטות הבקשה לכל הפרוטוקולים. לדוגמא אינך יכול לשלוח בקשת POST ב-Gopher.

++

שרת ה Squid אינו תומך בכל שיטות הבקשה לכל הפרוטוקולים. לדוגמא אינך יכול לשלוח בקשת.

+ +

מנהל השרת הוא %w.

+
+diff --git a/errors/hu/ERR_UNSUP_REQ b/errors/hu/ERR_UNSUP_REQ +index a7a6e43..d1602da 100644 +--- a/errors/hu/ERR_UNSUP_REQ ++++ b/errors/hu/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Nem támogatott kéréstípus vagy protokoll

+ + +-

A proxyszerver nem támogat minden létező kéréstípus és protokoll kombinációt, így pl. nem lehet POST kéréstípust használni egy Gopher kérésben.

++

A proxyszerver nem támogat minden létező kéréstípus és protokoll kombinációt.

+ +

A proxyszerver üzemeltetőjének e-mail címe: %w.

+
+diff --git a/errors/hy/ERR_UNSUP_REQ b/errors/hy/ERR_UNSUP_REQ +index 0a3cce7..db82035 100644 +--- a/errors/hy/ERR_UNSUP_REQ ++++ b/errors/hy/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Հարցում իրականացնելու մեթոդը և արձանագրությունը չեն աջակցվում

+ + +-

Squid-ը բոլոր արձանագրությունների համար բոլոր հարցման մեթոդները չի աջակցում. Օրինակ, Gopher արձանագրության համար չեք կարող POST հարցում կատարել.

++

Squid-ը բոլոր արձանագրությունների համար բոլոր հարցման մեթոդները չի աջակցում.

+ +

Ձեր քեշի կառավարիչը %w է.

+
+diff --git a/errors/id/ERR_UNSUP_REQ b/errors/id/ERR_UNSUP_REQ +index 352399d..e208043 100644 +--- a/errors/id/ERR_UNSUP_REQ ++++ b/errors/id/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/it/ERR_UNSUP_REQ b/errors/it/ERR_UNSUP_REQ +index d6ebc13..4f770bb 100644 +--- a/errors/it/ERR_UNSUP_REQ ++++ b/errors/it/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Metodo e protocollo della richiesta non sono supportati.

+ + +-

Squid non consente di utilizzare qualsiasi tipo di richiesta per qualsiasi protocollo (a esempio non consente una richiesta POST su protocollo Gopher).

++

Squid non consente di utilizzare qualsiasi tipo di richiesta per qualsiasi protocollo.

+ +

L'amministratore del proxy è %w.

+
+diff --git a/errors/ja/ERR_UNSUP_REQ b/errors/ja/ERR_UNSUP_REQ +index 67b6cf2..a7b7950 100644 +--- a/errors/ja/ERR_UNSUP_REQ ++++ b/errors/ja/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

サポートしていないリクエストメソッドとプロトコルです。

+ + +-

Squidはすべてのアクセス・プロトコルに対して、すべてのリクエストメソッドをサポートしているわけではありません。例えば、POSTをGopherのリクエストで行うことはできません。

++

Squidはすべてのアクセス・プロトコルに対して、すべてのリクエストメソッドをサポートしているわけではありません。

+ +

Your cache administrator is %w.

+
+diff --git a/errors/ka/ERR_UNSUP_REQ b/errors/ka/ERR_UNSUP_REQ +index 1238302..8d2c62e 100644 +--- a/errors/ka/ERR_UNSUP_REQ ++++ b/errors/ka/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.

+ +

თქვენი კეშის ადმინისტრატორია %w.

+
+diff --git a/errors/ko/ERR_UNSUP_REQ b/errors/ko/ERR_UNSUP_REQ +index d19ce25..ca7c946 100644 +--- a/errors/ko/ERR_UNSUP_REQ ++++ b/errors/ko/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

지원되지 않는 Request Method와 프로토콜입니다.

+ + +-

Squid는 모든 접속 프로토콜에 대한 request method를 지원하지 않습니다. 한가지 예로, Gopher에서 POST request를 사용할 수 없습니다.

++

Squid는 모든 접속 프로토콜에 대한 request method를 지원하지 않습니다.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/lt/ERR_UNSUP_REQ b/errors/lt/ERR_UNSUP_REQ +index 9e3949b..29af2de 100644 +--- a/errors/lt/ERR_UNSUP_REQ ++++ b/errors/lt/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Nepalaikomas užklausos metodas ir protokolas

+ + +-

Squid palaiko ne visus užklausos metodus daliai protokolų. Pavyzdžiui, jūs negalite vykdyti POST Gopher tipo užklausoje.

++

Squid palaiko ne visus užklausos metodus daliai protokolų.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/lv/ERR_UNSUP_REQ b/errors/lv/ERR_UNSUP_REQ +index 85450e6..88bfc8b 100644 +--- a/errors/lv/ERR_UNSUP_REQ ++++ b/errors/lv/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Neatbalstīta pieprasījuma metode un protokols

+ + +-

Squid neatbalsta visas pieprasījuma metodes visiem protokoliem. Piemēram, Jūs nevarat veikt POST pieprasījumu izmantojot Gopher protokolu.

++

Squid neatbalsta visas pieprasījuma metodes visiem protokoliem.

+ +

Jūsu kešatmiņas administrators ir %w.

+
+diff --git a/errors/ms/ERR_UNSUP_REQ b/errors/ms/ERR_UNSUP_REQ +index 987fe76..20948f5 100644 +--- a/errors/ms/ERR_UNSUP_REQ ++++ b/errors/ms/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.

+ +

Pengurus Proxy anda ialah %w.

+
+diff --git a/errors/nl/ERR_UNSUP_REQ b/errors/nl/ERR_UNSUP_REQ +index a8cb984..c46c47a 100644 +--- a/errors/nl/ERR_UNSUP_REQ ++++ b/errors/nl/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Niet ondersteunde verzoekmethode of protocol

+ + +-

Squid ondersteunt niet alle verzoekmethoden voor alle toegangsprotocollen. U kunt bijvoorbeeld geen Gopher verzoek POSTen.

++

Squid ondersteunt niet alle verzoekmethoden voor alle toegangsprotocollen.

+ +

De beheerder van deze cache is %w.

+
+diff --git a/errors/oc/ERR_UNSUP_REQ b/errors/oc/ERR_UNSUP_REQ +index 617f4a9..4e2ea38 100644 +--- a/errors/oc/ERR_UNSUP_REQ ++++ b/errors/oc/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.

+ +

Vòstre administrator d'amagatal es %w.

+
+diff --git a/errors/pl/ERR_UNSUP_REQ b/errors/pl/ERR_UNSUP_REQ +index 44bc0de..64c594c 100644 +--- a/errors/pl/ERR_UNSUP_REQ ++++ b/errors/pl/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

użyta w żądaniu kombinacja metoda/protokół jest niewłaściwa

+ + +-

Squid nie wspiera wszystkich metod we wszystkich protokołach. Na przykład nie możesz użyć metody POST w żądaniu skierowanym do usługi Gopher.

++

Squid nie wspiera wszystkich metod we wszystkich protokołach.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/pt-br/ERR_UNSUP_REQ b/errors/pt-br/ERR_UNSUP_REQ +index 60e08d3..5fbc882 100644 +--- a/errors/pt-br/ERR_UNSUP_REQ ++++ b/errors/pt-br/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Método e Protocolo de Requisição Não-Suportado

+ + +-

Squid não suporta todos os métodos de requisição para todos os protocolos de acesso. Por exemplo, você não pode emitir uma requisição POST ao protocolo Gopher.

++

Squid não suporta todos os métodos de requisição para todos os protocolos de acesso.

+ +

Seu administrador do cache é %w.

+
+diff --git a/errors/pt/ERR_UNSUP_REQ b/errors/pt/ERR_UNSUP_REQ +index ed3a68b..4b8bbbb 100644 +--- a/errors/pt/ERR_UNSUP_REQ ++++ b/errors/pt/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Método ou protocolo não suportado.

+ + +-

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/ro/ERR_UNSUP_REQ b/errors/ro/ERR_UNSUP_REQ +index f97375f..a237af2 100644 +--- a/errors/ro/ERR_UNSUP_REQ ++++ b/errors/ro/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Metodă de cerere şi protocol nesuportată

+ + +-

Squid nu suportă toate metodele de cerere pentru toate protocoalele de acces. De exemplu, nu puteţi face o cerere de tip POST pentru Gopher.

++

Squid nu suportă toate metodele de cerere pentru toate protocoalele de acces.

+ +

Administratorul cache-ului este %w.

+
+diff --git a/errors/ru/ERR_UNSUP_REQ b/errors/ru/ERR_UNSUP_REQ +index 2a22302..b7fa536 100644 +--- a/errors/ru/ERR_UNSUP_REQ ++++ b/errors/ru/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Неподдерживаемый метод запроса или протокол

+ + +-

Squid не поддерживает все методы запросов для всех протоколов. К примеру, для протокола Gopher Вы не можете выполнить запрос POST.

++

Squid не поддерживает все методы запросов для всех протоколов.

+ +

Администратор Вашего кэша: %w.

+
+diff --git a/errors/sk/ERR_UNSUP_REQ b/errors/sk/ERR_UNSUP_REQ +index 4c37736..aecebc7 100644 +--- a/errors/sk/ERR_UNSUP_REQ ++++ b/errors/sk/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Nepodporovaná metóda a protokol požiadavky

+ + +-

Squid nepodporuje všetky typy metód pri všetkých protokoloch. Napríklad: nie je možné použiť metódu POST pri službe Gopher.

++

Squid nepodporuje všetky typy metód pri všetkých protokoloch.

+ +

Vaším správcom cache je %w.

+
+diff --git a/errors/sl/ERR_UNSUP_REQ b/errors/sl/ERR_UNSUP_REQ +index 3fff99a..7d421a5 100644 +--- a/errors/sl/ERR_UNSUP_REQ ++++ b/errors/sl/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Nepodprta metoda zahteve in protokol

+ + +-

Squid ne podpira vseh metod zahtev za vse protokole dostopa. Tako npr. metode POST ne morete uporabiti za zahtevo Gopher.

++

Squid ne podpira vseh metod zahtev za vse protokole dostopa.

+ +

Skrbnik vašega predpomnilnika je %w.

+
+diff --git a/errors/sr-cyrl/ERR_UNSUP_REQ b/errors/sr-cyrl/ERR_UNSUP_REQ +index 352399d..e208043 100644 +--- a/errors/sr-cyrl/ERR_UNSUP_REQ ++++ b/errors/sr-cyrl/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/sr-latn/ERR_UNSUP_REQ b/errors/sr-latn/ERR_UNSUP_REQ +index 11ba17b..64ee787 100644 +--- a/errors/sr-latn/ERR_UNSUP_REQ ++++ b/errors/sr-latn/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Nepodržan metod ili protokol zahteva (Request)

+ + +-

Squid Proksi server ne podržava sve metode zahteva za sve moguæe pristupne protokole. Na primer ne možete da uradite POST na Gopher zahtev.

++

Squid Proksi server ne podržava sve metode zahteva za sve moguæe pristupne protokole.

+ +

Vaš keš/proksi administrator je: %w.

+
+diff --git a/errors/sv/ERR_UNSUP_REQ b/errors/sv/ERR_UNSUP_REQ +index 0fcb988..d7fdeef 100644 +--- a/errors/sv/ERR_UNSUP_REQ ++++ b/errors/sv/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Ej stöd för begärd Metod och Protokoll

+ + +-

Squid stödjer inte alla frågemetoder för alla protokoll. Till exempel, Ni kan inte POST'a en Gopher förfrågan.

++

Squid stödjer inte alla frågemetoder för alla protokoll.

+ +

Din cacheserver administratör är %w.

+
+diff --git a/errors/templates/ERR_UNSUP_REQ b/errors/templates/ERR_UNSUP_REQ +index e880392..196887d 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/errors/th/ERR_UNSUP_REQ b/errors/th/ERR_UNSUP_REQ +index d34fc2d..9586681 100644 +--- a/errors/th/ERR_UNSUP_REQ ++++ b/errors/th/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

ไม่รองรับโปรโตคอลและวิธีการหรือคำสั่งที่เรียกมา (request method)

+ + +-

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.

+ +

ผู้ดูแลระบบแคชของคุณคือ %w

+
+diff --git a/errors/tr/ERR_UNSUP_REQ b/errors/tr/ERR_UNSUP_REQ +index 9c00be4..90db4b7 100644 +--- a/errors/tr/ERR_UNSUP_REQ ++++ b/errors/tr/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Desteklenmeyen istek yöntemi ve protokol.

+ + +-

Squid, bazı erişim protokollerin, bazı istek yöntemlerini desteklemiyor. Örneğin Gopher isteğinizde POST yapamazsınız.

++

Squid, bazı erişim protokollerin, bazı istek yöntemlerini desteklemiyor.

+ +

Önbellk yöneticiniz %w.

+
+diff --git a/errors/uk/ERR_UNSUP_REQ b/errors/uk/ERR_UNSUP_REQ +index d92e9e5..4ffb93e 100644 +--- a/errors/uk/ERR_UNSUP_REQ ++++ b/errors/uk/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Метод запиту чи протокол не підтримуються

+ + +-

Squid не підтримує всі методи запитів для всіх наявних протоколів. Як приклад, Ви не можете виконати запит POST для протоколу Gopher.

++

Squid не підтримує всі методи запитів для всіх наявних протоколів.

+ +

Адміністратор даного кешу %w.

+
+diff --git a/errors/uz/ERR_UNSUP_REQ b/errors/uz/ERR_UNSUP_REQ +index 47f5fe9..7c4cfa7 100644 +--- a/errors/uz/ERR_UNSUP_REQ ++++ b/errors/uz/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/vi/ERR_UNSUP_REQ b/errors/vi/ERR_UNSUP_REQ +index 807df9e..f84d447 100644 +--- a/errors/vi/ERR_UNSUP_REQ ++++ b/errors/vi/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

Unsupported Request Method and Protocol

+ + +-

Squid không hỗ trợ tất cả các phương pháp yêu cầu cho mỗi giao thức truy cập. Chẳng hạn, bạn không có khả năng POST một yêu cầu Gopher.

++

Squid không hỗ trợ tất cả các phương pháp yêu cầu cho mỗi giao thức truy cập.

+ +

Your cache administrator is %w.

+
+diff --git a/errors/zh-hans/ERR_UNSUP_REQ b/errors/zh-hans/ERR_UNSUP_REQ +index 056c22b..35b28a3 100644 +--- a/errors/zh-hans/ERR_UNSUP_REQ ++++ b/errors/zh-hans/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

不支持的请求方式和协议

+ + +-

Squid (缓存服务器)不能对所有的存取协议支持所有的请求方式。比如说,你不能对 GOPHER 进行一个 POST 请求。

++

Squid (缓存服务器)不能对所有的存取协议支持所有的请求方式。

+ +

缓存服务器的管理员 %w.

+
+diff --git a/errors/zh-hant/ERR_UNSUP_REQ b/errors/zh-hant/ERR_UNSUP_REQ +index eacf4c4..8023a8b 100644 +--- a/errors/zh-hant/ERR_UNSUP_REQ ++++ b/errors/zh-hant/ERR_UNSUP_REQ +@@ -24,7 +24,7 @@ body +

尚未支援的要求方式或通訊協定

+ + +-

因為 Squid (網路快取程式)並未支援所有的連結要求方式在各式通訊協定上。比如說,你不能要求一個 GOPHER 的 POST 連結要求。

++

因為 Squid (網路快取程式)並未支援所有的連結要求方式在各式通訊協定上。

+ +

Your cache administrator is %w.

+
+diff --git a/src/FwdState.cc b/src/FwdState.cc +index 41a1679..5363572 100644 +--- a/src/FwdState.cc ++++ b/src/FwdState.cc +@@ -28,7 +28,6 @@ + #include "fde.h" + #include "FwdState.h" + #include "globals.h" +-#include "gopher.h" + #include "hier_code.h" + #include "http.h" + #include "http/Stream.h" +@@ -1007,10 +1006,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/HttpMsg.h b/src/HttpMsg.h +index 2bf799f..06ef081 100644 +--- a/src/HttpMsg.h ++++ b/src/HttpMsg.h +@@ -38,7 +38,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/HttpRequest.cc b/src/HttpRequest.cc +index 0c11f5a..38b9307 100644 +--- a/src/HttpRequest.cc ++++ b/src/HttpRequest.cc +@@ -18,7 +18,6 @@ + #include "Downloader.h" + #include "err_detail_type.h" + #include "globals.h" +-#include "gopher.h" + #include "http.h" + #include "http/one/RequestParser.h" + #include "http/Stream.h" +@@ -556,11 +555,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 e04deef..0b69d41 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 7189757..cbce754 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -306,8 +306,6 @@ squid_SOURCES = \ + FwdState.h \ + Generic.h \ + globals.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + helper.h \ + hier_code.h \ +@@ -1260,8 +1258,6 @@ tests_testCacheManager_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + hier_code.h \ + helper.cc \ + $(HTCPSOURCE) \ +@@ -1679,8 +1675,6 @@ tests_testEvent_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -1915,8 +1909,6 @@ tests_testEventLoop_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -2146,8 +2138,6 @@ tests_test_http_range_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -2462,8 +2452,6 @@ tests_testHttpRequest_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -3308,8 +3296,6 @@ tests_testURL_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +diff --git a/src/Makefile.in b/src/Makefile.in +index 53ac16d..d46f49c 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -263,7 +263,7 @@ am__squid_SOURCES_DIST = AclRegs.cc AuthReg.cc AccessLogEntry.cc \ + ExternalACL.h ExternalACLEntry.cc ExternalACLEntry.h \ + FadingCounter.h FadingCounter.cc fatal.h fatal.cc fd.h fd.cc \ + fde.cc fde.h FileMap.h filemap.cc fqdncache.h fqdncache.cc \ +- FwdState.cc FwdState.h Generic.h globals.h gopher.h gopher.cc \ ++ FwdState.cc FwdState.h Generic.h globals.h \ + helper.cc helper.h hier_code.h HierarchyLogEntry.h htcp.cc \ + htcp.h http.cc http.h HttpHeaderFieldStat.h HttpHdrCc.h \ + HttpHdrCc.cc HttpHdrCc.cci HttpHdrRange.cc HttpHdrSc.cc \ +@@ -352,7 +352,7 @@ am_squid_OBJECTS = $(am__objects_1) AccessLogEntry.$(OBJEXT) \ + EventLoop.$(OBJEXT) external_acl.$(OBJEXT) \ + ExternalACLEntry.$(OBJEXT) FadingCounter.$(OBJEXT) \ + fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \ +- fqdncache.$(OBJEXT) FwdState.$(OBJEXT) gopher.$(OBJEXT) \ ++ fqdncache.$(OBJEXT) FwdState.$(OBJEXT) \ + helper.$(OBJEXT) $(am__objects_5) http.$(OBJEXT) \ + HttpHdrCc.$(OBJEXT) HttpHdrRange.$(OBJEXT) HttpHdrSc.$(OBJEXT) \ + HttpHdrScTarget.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \ +@@ -539,7 +539,7 @@ am__tests_testCacheManager_SOURCES_DIST = AccessLogEntry.cc debug.cc \ + tests/stub_ETag.cc event.cc external_acl.cc \ + ExternalACLEntry.cc fatal.h tests/stub_fatal.cc fd.h fd.cc \ + fde.cc FileMap.h filemap.cc fqdncache.h fqdncache.cc \ +- FwdState.cc FwdState.h gopher.h gopher.cc hier_code.h \ ++ FwdState.cc FwdState.h hier_code.h \ + helper.cc htcp.cc htcp.h http.cc HttpBody.h HttpBody.cc \ + HttpHeader.h HttpHeader.cc HttpHeaderFieldInfo.h \ + HttpHeaderTools.h HttpHeaderTools.cc HttpHeaderFieldStat.h \ +@@ -594,7 +594,7 @@ am_tests_testCacheManager_OBJECTS = AccessLogEntry.$(OBJEXT) \ + event.$(OBJEXT) external_acl.$(OBJEXT) \ + ExternalACLEntry.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \ + fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \ +- fqdncache.$(OBJEXT) FwdState.$(OBJEXT) gopher.$(OBJEXT) \ ++ fqdncache.$(OBJEXT) FwdState.$(OBJEXT) \ + helper.$(OBJEXT) $(am__objects_5) http.$(OBJEXT) \ + HttpBody.$(OBJEXT) HttpHeader.$(OBJEXT) \ + HttpHeaderTools.$(OBJEXT) HttpHdrCc.$(OBJEXT) \ +@@ -838,7 +838,7 @@ am__tests_testEvent_SOURCES_DIST = AccessLogEntry.cc BodyPipe.cc \ + EventLoop.h EventLoop.cc external_acl.cc ExternalACLEntry.cc \ + FadingCounter.cc fatal.h tests/stub_fatal.cc fd.h fd.cc fde.cc \ + FileMap.h filemap.cc fqdncache.h fqdncache.cc FwdState.cc \ +- FwdState.h gopher.h gopher.cc helper.cc hier_code.h htcp.cc \ ++ FwdState.h helper.cc hier_code.h htcp.cc \ + htcp.h http.cc HttpBody.h HttpBody.cc \ + tests/stub_HttpControlMsg.cc HttpHeader.h HttpHeader.cc \ + HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \ +@@ -891,7 +891,7 @@ am_tests_testEvent_OBJECTS = AccessLogEntry.$(OBJEXT) \ + external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \ + FadingCounter.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \ + fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \ +- fqdncache.$(OBJEXT) FwdState.$(OBJEXT) gopher.$(OBJEXT) \ ++ fqdncache.$(OBJEXT) FwdState.$(OBJEXT) \ + helper.$(OBJEXT) $(am__objects_5) http.$(OBJEXT) \ + HttpBody.$(OBJEXT) tests/stub_HttpControlMsg.$(OBJEXT) \ + HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ +@@ -975,8 +975,8 @@ am__tests_testEventLoop_SOURCES_DIST = AccessLogEntry.cc BodyPipe.cc \ + tests/stub_ETag.cc EventLoop.h EventLoop.cc event.cc \ + external_acl.cc ExternalACLEntry.cc FadingCounter.cc fatal.h \ + tests/stub_fatal.cc fd.h fd.cc fde.cc FileMap.h filemap.cc \ +- fqdncache.h fqdncache.cc FwdState.cc FwdState.h gopher.h \ +- gopher.cc helper.cc hier_code.h htcp.cc htcp.h http.cc \ ++ fqdncache.h fqdncache.cc FwdState.cc FwdState.h \ ++ helper.cc hier_code.h htcp.cc htcp.h http.cc \ + HttpBody.h HttpBody.cc tests/stub_HttpControlMsg.cc \ + HttpHeader.h HttpHeader.cc HttpHeaderFieldInfo.h \ + HttpHeaderTools.h HttpHeaderTools.cc HttpHeaderFieldStat.h \ +@@ -1029,7 +1029,7 @@ am_tests_testEventLoop_OBJECTS = AccessLogEntry.$(OBJEXT) \ + external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \ + FadingCounter.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \ + fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \ +- fqdncache.$(OBJEXT) FwdState.$(OBJEXT) gopher.$(OBJEXT) \ ++ fqdncache.$(OBJEXT) FwdState.$(OBJEXT) \ + helper.$(OBJEXT) $(am__objects_5) http.$(OBJEXT) \ + HttpBody.$(OBJEXT) tests/stub_HttpControlMsg.$(OBJEXT) \ + HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ +@@ -1187,7 +1187,7 @@ am__tests_testHttpRequest_SOURCES_DIST = AccessLogEntry.cc \ + fs_io.cc dlink.h dlink.cc dns_internal.cc errorpage.cc \ + tests/stub_ETag.cc external_acl.cc ExternalACLEntry.cc fatal.h \ + tests/stub_fatal.cc fd.h fd.cc fde.cc fqdncache.h fqdncache.cc \ +- FwdState.cc FwdState.h gopher.h gopher.cc helper.cc \ ++ FwdState.cc FwdState.h helper.cc \ + hier_code.h htcp.cc htcp.h http.cc HttpBody.h HttpBody.cc \ + tests/stub_HttpControlMsg.cc HttpHeader.h HttpHeader.cc \ + HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \ +@@ -1243,7 +1243,7 @@ am_tests_testHttpRequest_OBJECTS = AccessLogEntry.$(OBJEXT) \ + $(am__objects_4) errorpage.$(OBJEXT) tests/stub_ETag.$(OBJEXT) \ + external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \ + tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \ +- fqdncache.$(OBJEXT) FwdState.$(OBJEXT) gopher.$(OBJEXT) \ ++ fqdncache.$(OBJEXT) FwdState.$(OBJEXT) \ + helper.$(OBJEXT) $(am__objects_5) http.$(OBJEXT) \ + HttpBody.$(OBJEXT) tests/stub_HttpControlMsg.$(OBJEXT) \ + HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ +@@ -1670,8 +1670,8 @@ am__tests_testURL_SOURCES_DIST = AccessLogEntry.cc BodyPipe.cc \ + fs_io.cc dlink.h dlink.cc dns_internal.cc errorpage.cc ETag.cc \ + event.cc external_acl.cc ExternalACLEntry.cc fatal.h \ + tests/stub_fatal.cc fd.h fd.cc fde.cc FileMap.h filemap.cc \ +- fqdncache.h fqdncache.cc FwdState.cc FwdState.h gopher.h \ +- gopher.cc helper.cc hier_code.h htcp.cc htcp.h http.cc \ ++ fqdncache.h fqdncache.cc FwdState.cc FwdState.h \ ++ helper.cc hier_code.h htcp.cc htcp.h http.cc \ + HttpBody.h HttpBody.cc tests/stub_HttpControlMsg.cc \ + HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ +@@ -1725,7 +1725,7 @@ am_tests_testURL_OBJECTS = AccessLogEntry.$(OBJEXT) BodyPipe.$(OBJEXT) \ + event.$(OBJEXT) external_acl.$(OBJEXT) \ + ExternalACLEntry.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \ + fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \ +- fqdncache.$(OBJEXT) FwdState.$(OBJEXT) gopher.$(OBJEXT) \ ++ fqdncache.$(OBJEXT) FwdState.$(OBJEXT) \ + helper.$(OBJEXT) $(am__objects_5) http.$(OBJEXT) \ + HttpBody.$(OBJEXT) tests/stub_HttpControlMsg.$(OBJEXT) \ + HttpHdrCc.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \ +@@ -1925,8 +1925,8 @@ am__tests_test_http_range_SOURCES_DIST = AccessLogEntry.cc BodyPipe.cc \ + dns_internal.cc errorpage.cc tests/stub_ETag.cc event.cc \ + FadingCounter.cc fatal.h tests/stub_libauth.cc \ + tests/stub_fatal.cc fd.h fd.cc fde.cc FileMap.h filemap.cc \ +- fqdncache.h fqdncache.cc FwdState.cc FwdState.h gopher.h \ +- gopher.cc helper.cc hier_code.h htcp.cc htcp.h http.cc \ ++ fqdncache.h fqdncache.cc FwdState.cc FwdState.h \ ++ helper.cc hier_code.h htcp.cc htcp.h http.cc \ + HttpBody.h HttpBody.cc tests/stub_HttpControlMsg.cc \ + HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ +@@ -1979,7 +1979,7 @@ am_tests_test_http_range_OBJECTS = AccessLogEntry.$(OBJEXT) \ + FadingCounter.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \ + tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \ + filemap.$(OBJEXT) fqdncache.$(OBJEXT) FwdState.$(OBJEXT) \ +- gopher.$(OBJEXT) helper.$(OBJEXT) $(am__objects_5) \ ++ helper.$(OBJEXT) $(am__objects_5) \ + http.$(OBJEXT) HttpBody.$(OBJEXT) \ + tests/stub_HttpControlMsg.$(OBJEXT) HttpHdrCc.$(OBJEXT) \ + HttpHdrContRange.$(OBJEXT) HttpHdrRange.$(OBJEXT) \ +@@ -2131,7 +2131,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 \ +@@ -3046,7 +3046,7 @@ squid_SOURCES = $(ACL_REGISTRATION_SOURCES) AccessLogEntry.cc \ + ExternalACL.h ExternalACLEntry.cc ExternalACLEntry.h \ + FadingCounter.h FadingCounter.cc fatal.h fatal.cc fd.h fd.cc \ + fde.cc fde.h FileMap.h filemap.cc fqdncache.h fqdncache.cc \ +- FwdState.cc FwdState.h Generic.h globals.h gopher.h gopher.cc \ ++ FwdState.cc FwdState.h Generic.h globals.h \ + helper.cc helper.h hier_code.h HierarchyLogEntry.h \ + $(HTCPSOURCE) http.cc http.h HttpHeaderFieldStat.h HttpHdrCc.h \ + HttpHdrCc.cc HttpHdrCc.cci HttpHdrRange.cc HttpHdrSc.cc \ +@@ -3711,8 +3711,6 @@ tests_testCacheManager_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + hier_code.h \ + helper.cc \ + $(HTCPSOURCE) \ +@@ -4137,8 +4135,6 @@ tests_testEvent_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -4374,8 +4370,6 @@ tests_testEventLoop_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -4607,8 +4601,6 @@ tests_test_http_range_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -4927,8 +4919,6 @@ tests_testHttpRequest_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -5780,8 +5770,6 @@ tests_testURL_SOURCES = \ + fqdncache.cc \ + FwdState.cc \ + FwdState.h \ +- gopher.h \ +- gopher.cc \ + helper.cc \ + hier_code.h \ + $(HTCPSOURCE) \ +@@ -6826,7 +6814,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 +@@ -7808,7 +7795,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 +@@ -8133,7 +8119,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 +diff --git a/src/adaptation/ecap/Host.cc b/src/adaptation/ecap/Host.cc +index 33fbb5a..5f17f86 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 a2779e7..94595b6 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.cc b/src/anyp/ProtocolType.cc +index 7b8c3ef..9b92c79 100644 +--- a/src/anyp/ProtocolType.cc ++++ b/src/anyp/ProtocolType.cc +@@ -13,7 +13,6 @@ const char * ProtocolType_str[] = { + "HTTPS", + "COAP", + "COAPS", +- "GOPHER", + "WAIS", + "CACHE_OBJECT", + "ICP", +diff --git a/src/anyp/ProtocolType.h b/src/anyp/ProtocolType.h +index 66f7bc2..ef3ab25 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 ced3181..b0b60cf 100644 +--- a/src/anyp/Uri.cc ++++ b/src/anyp/Uri.cc +@@ -885,8 +885,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 bac5435..f96c73f 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 b5519b2..bc2ddcd 100644 +--- a/src/cf.data.pre ++++ b/src/cf.data.pre +@@ -1513,7 +1513,6 @@ acl SSL_ports port 443 + acl Safe_ports port 80 # http + acl Safe_ports port 21 # ftp + acl Safe_ports port 443 # https +-acl Safe_ports port 70 # gopher + acl Safe_ports port 210 # wais + acl Safe_ports port 1025-65535 # unregistered ports + acl Safe_ports port 280 # http-mgmt +@@ -4563,7 +4562,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/err_type.h b/src/err_type.h +index 742fc5a..dbb4527 100644 +--- a/src/err_type.h ++++ b/src/err_type.h +@@ -65,7 +65,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 6187da1..0000000 +--- a/src/gopher.cc ++++ /dev/null +@@ -1,977 +0,0 @@ +-/* +- * Copyright (C) 1996-2021 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' */), +- cso_recno(0), +- len(0), +- buf(NULL), +- fwd(aFwd) +- { +- *request = 0; +- buf = (char *)memAllocate(MEM_4K_BUF); +- entry->lock("gopherState"); +- *replybuf = 0; +- } +- ~GopherStateData() {if(buf) swanSong();} +- +- /* AsyncJob API emulated */ +- void deleteThis(const char *aReason); +- void swanSong(); +- +-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]; +- int cso_recno; +- 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; +- +- if (gopherState == NULL) +- return; +- +- gopherState->deleteThis("gopherStateFree"); +-} +- +-void +-GopherStateData::deleteThis(const char *) +-{ +- swanSong(); +- delete this; +-} +- +-void +-GopherStateData::swanSong() +-{ +- if (entry) +- entry->unlock("gopherState"); +- +- if (buf) { +- memFree(buf, MEM_4K_BUF); +- buf = nullptr; +- } +-} +- +-/** +- * 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;
+-        }
+-        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));
+-
+-    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 |= HttpMsg::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 {
+-            ErrorState *err = new ErrorState(ERR_READ_ERROR, Http::scInternalServerError, gopherState->fwd->request);
+-            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->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();
+-        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) {
+-        ErrorState *err;
+-        err = new ErrorState(ERR_WRITE_ERROR, Http::scServiceUnavailable, gopherState->fwd->request);
+-        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->complete();
+-        return;
+-    }
+-
+-    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.cc.CVE-2021-46784 b/src/gopher.cc.CVE-2021-46784
+deleted file mode 100644
+index 169b0e1..0000000
+--- a/src/gopher.cc.CVE-2021-46784
++++ /dev/null
+@@ -1,982 +0,0 @@
+-/*
+- * Copyright (C) 1996-2021 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' */),
+-        cso_recno(0),
+-        len(0),
+-        buf(NULL),
+-        fwd(aFwd)
+-    {
+-        *request = 0;
+-        buf = (char *)memAllocate(MEM_4K_BUF);
+-        entry->lock("gopherState");
+-        *replybuf = 0;
+-    }
+-    ~GopherStateData() {if(buf) swanSong();}
+-
+-    /* AsyncJob API emulated */
+-    void deleteThis(const char *aReason);
+-    void swanSong();
+-
+-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];
+-    int cso_recno;
+-    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;
+-
+-    if (gopherState == NULL)
+-        return;
+-
+-    gopherState->deleteThis("gopherStateFree");
+-}
+-
+-void
+-GopherStateData::deleteThis(const char *)
+-{
+-    swanSong();
+-    delete this;
+-}
+-
+-void
+-GopherStateData::swanSong()
+-{
+-    if (entry)
+-        entry->unlock("gopherState");
+-
+-    if (buf) {
+-        memFree(buf, MEM_4K_BUF);
+-        buf = nullptr;
+-    }
+-}
+-
+-/**
+- * 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); +- LOCAL_ARRAY(char, tmpbuf, 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(tmpbuf, '\0', TEMP_BUF_SIZE); +- 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; +- } +- +- String 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;
+-        }
+-        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;
+-                    }
+-
+-                    memset(tmpbuf, '\0', TEMP_BUF_SIZE);
+-
+-                    if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) {
+-                        if (strlen(escaped_selector) != 0)
+-                            snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
+-                                     icon_url, escaped_selector, rfc1738_escape_part(host),
+-                                     *port ? ":" : "", port, html_quote(name));
+-                        else
+-                            snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
+-                                     icon_url, rfc1738_escape_part(host), *port ? ":" : "",
+-                                     port, html_quote(name));
+-
+-                    } else if (gtype == GOPHER_INFO) {
+-                        snprintf(tmpbuf, TEMP_BUF_SIZE, "\t%s\n", html_quote(name));
+-                    } else {
+-                        if (strncmp(selector, "GET /", 5) == 0) {
+-                            /* WWW link */
+-                            snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
+-                                     icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name));
+-                        } else {
+-                            /* Standard link */
+-                            snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n",
+-                                     icon_url, host, gtype, escaped_selector, html_quote(name));
+-                        }
+-                    }
+-
+-                    safe_free(escaped_selector);
+-                    outbuf.append(tmpbuf);
+-                } 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) {
+-                    snprintf(tmpbuf, TEMP_BUF_SIZE, "

Record# %d
%s

\n
", recno, html_quote(result));
+-                    gopherState->cso_recno = recno;
+-                } else {
+-                    snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", html_quote(result));
+-                }
+-
+-                outbuf.append(tmpbuf);
+-                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 */
+-                    snprintf(tmpbuf, TEMP_BUF_SIZE, "

%s

\n
", html_quote(result));
+-                    outbuf.append(tmpbuf);
+-                    break;
+-                }
+-
+-                }
+-            }
+-
+-            }           /* HTML_CSO_RESULT */
+-
+-        default:
+-            break;      /* do nothing */
+-
+-        }           /* switch */
+-
+-    }               /* while loop */
+-
+-    if (outbuf.size() > 0) {
+-        entry->append(outbuf.rawBuf(), outbuf.size());
+-        /* now let start sending stuff to client */
+-        entry->flush();
+-    }
+-
+-    outbuf.clean();
+-    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));
+-
+-    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 |= HttpMsg::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 {
+-            ErrorState *err = new ErrorState(ERR_READ_ERROR, Http::scInternalServerError, gopherState->fwd->request);
+-            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->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();
+-        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) {
+-        ErrorState *err;
+-        err = new ErrorState(ERR_WRITE_ERROR, Http::scServiceUnavailable, gopherState->fwd->request);
+-        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->complete();
+-        return;
+-    }
+-
+-    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 1d73bac..0000000
+--- a/src/gopher.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-/*
+- * Copyright (C) 1996-2021 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/mgr/IoAction.cc b/src/mgr/IoAction.cc
+index 149f2c4..e48a2e0 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 32de089..f11ade7 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 11135c3..bfffd91 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 8a59be4..9f2ac49 100644
+--- a/src/stat.cc
++++ b/src/stat.cc
+@@ -207,11 +207,6 @@ GetIoStats(Mgr::IoActionData& stats)
+         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,18 +239,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/test-suite/squidconf/regressions-3.4.0.1 b/test-suite/squidconf/regressions-3.4.0.1
+index 41a441b..85f0a64 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
+-- 
+2.39.3
+
diff --git a/SOURCES/squid-4.15-CVE-2023-49285.patch b/SOURCES/squid-4.15-CVE-2023-49285.patch
new file mode 100644
index 0000000..59ebd5a
--- /dev/null
+++ b/SOURCES/squid-4.15-CVE-2023-49285.patch
@@ -0,0 +1,38 @@
+commit deee944f9a12c9fd399ce52f3e2526bb573a9470
+Author: Alex Rousskov 
+Date:   Wed Oct 25 19:41:45 2023 +0000
+
+    RFC 1123: Fix date parsing (#1538)
+
+    The bug was discovered and detailed by Joshua Rogers at
+    https://megamansec.github.io/Squid-Security-Audit/datetime-overflow.html
+    where it was filed as "1-Byte Buffer OverRead in RFC 1123 date/time
+    Handling".
+
+Back port upstream patch
+Signed-Off-By: tianyue.lan@oracle.com
+---
+ lib/rfc1123.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/lib/rfc1123.c b/lib/rfc1123.c
+index 2d889cc..add63f0 100644
+--- a/lib/rfc1123.c
++++ b/lib/rfc1123.c
+@@ -50,7 +50,13 @@ make_month(const char *s)
+     char month[3];
+ 
+     month[0] = xtoupper(*s);
++    if (!month[0])
++        return -1; // protects *(s + 1) below
++
+     month[1] = xtolower(*(s + 1));
++    if (!month[1])
++        return -1; // protects *(s + 2) below
++
+     month[2] = xtolower(*(s + 2));
+ 
+     for (i = 0; i < 12; i++)
+-- 
+2.39.3
+
diff --git a/SOURCES/squid-4.15-CVE-2023-49286.patch b/SOURCES/squid-4.15-CVE-2023-49286.patch
new file mode 100644
index 0000000..f151bc5
--- /dev/null
+++ b/SOURCES/squid-4.15-CVE-2023-49286.patch
@@ -0,0 +1,88 @@
+commit 6014c6648a2a54a4ecb7f952ea1163e0798f9264
+Author: Alex Rousskov 
+Date:   Fri Oct 27 21:27:20 2023 +0000
+
+    Exit without asserting when helper process startup fails (#1543)
+
+    ... to dup() after fork() and before execvp().
+
+    Assertions are for handling program logic errors. Helper initialization
+    code already handled system call errors correctly (i.e. by exiting the
+    newly created helper process with an error), except for a couple of
+    assert()s that could be triggered by dup(2) failures.
+
+    This bug was discovered and detailed by Joshua Rogers at
+    https://megamansec.github.io/Squid-Security-Audit/ipc-assert.html
+    where it was filed as 'Assertion in Squid "Helper" Process Creator'.
+
+Back port upstream patch
+Signed-Off-By: tianyue.lan@oracle.com
+---
+ src/ipc.cc | 32 ++++++++++++++++++++++++++------
+ 1 file changed, 26 insertions(+), 6 deletions(-)
+
+diff --git a/src/ipc.cc b/src/ipc.cc
+index e92a27f..3ddae70 100644
+--- a/src/ipc.cc
++++ b/src/ipc.cc
+@@ -19,6 +19,11 @@
+ #include "SquidConfig.h"
+ #include "SquidIpc.h"
+ #include "tools.h"
++#include 
++
++#if HAVE_UNISTD_H
++#include 
++#endif
+ 
+ static const char *hello_string = "hi there\n";
+ #ifndef HELLO_BUF_SZ
+@@ -365,6 +370,22 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name
+     }
+ 
+     PutEnvironment();
++
++    // A dup(2) wrapper that reports and exits the process on errors. The
++    // exiting logic is only suitable for this child process context.
++    const auto dupOrExit = [prog,name](const int oldFd) {
++        const auto newFd = dup(oldFd);
++        if (newFd < 0) {
++            const auto savedErrno = errno;
++            debugs(54, DBG_CRITICAL, "ERROR: Helper process initialization failure: " << name <<
++                   Debug::Extra << "helper (CHILD) PID: " << getpid() <<
++                   Debug::Extra << "helper program name: " << prog <<
++                   Debug::Extra << "dup(2) system call error for FD " << oldFd << ": " << xstrerr(savedErrno));
++            _exit(EXIT_FAILURE);
++        }
++        return newFd;
++    };
++
+     /*
+      * This double-dup stuff avoids problems when one of
+      *  crfd, cwfd, or debug_log are in the rage 0-2.
+@@ -372,17 +393,16 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name
+ 
+     do {
+         /* First make sure 0-2 is occupied by something. Gets cleaned up later */
+-        x = dup(crfd);
+-        assert(x > -1);
+-    } while (x < 3 && x > -1);
++        x = dupOrExit(crfd);
++    } while (x < 3);
+ 
+     close(x);
+ 
+-    t1 = dup(crfd);
++    t1 = dupOrExit(crfd);
+ 
+-    t2 = dup(cwfd);
++    t2 = dupOrExit(cwfd);
+ 
+-    t3 = dup(fileno(debug_log));
++    t3 = dupOrExit(fileno(debug_log));
+ 
+     assert(t1 > 2 && t2 > 2 && t3 > 2);
+ 
+-- 
+2.39.3
+
diff --git a/SPECS/squid.spec b/SPECS/squid.spec
index 73a14cc..2f8c257 100644
--- a/SPECS/squid.spec
+++ b/SPECS/squid.spec
@@ -2,7 +2,7 @@
 
 Name:     squid
 Version:  4.15
-Release:  7%{?dist}.3
+Release:  7%{?dist}.5
 Summary:  The Squid proxy caching server
 Epoch:    7
 # See CREDITS for breakdown of non GPLv2+ code
@@ -62,6 +62,10 @@ Patch1004: 0004-Remove-mem_hdr-freeDataUpto-assertion-1562.patch
 Patch1005: 0005-Backport-Add-Assure-as-a-replacement-for-problematic.patch
 Patch1006: 0006-Backport-additional-functions-for-SquidMath.patch
 Patch1007: 0007-Adapt-to-older-gcc-cleanup.patch
+Patch1008: squid-4.15-CVE-2023-46724.patch 
+Patch1009: squid-4.15-CVE-2023-46728.patch
+Patch1010: squid-4.15-CVE-2023-49285.patch
+Patch1011: squid-4.15-CVE-2023-49286.patch
 
 
 Requires: bash >= 2.0
@@ -142,6 +146,10 @@ lookup program (dnsserver), a program for retrieving FTP data
 %patch1005 -p1
 %patch1006 -p1
 %patch1007 -p1
+%patch1008 -p1
+%patch1009 -p1
+%patch1010 -p1
+%patch1011 -p1
 
 # https://bugzilla.redhat.com/show_bug.cgi?id=1679526
 # Patch in the vendor documentation and used different location for documentation
@@ -358,6 +366,12 @@ fi
 
 
 %changelog
+* Wed Jan 03 2024 Tianyue Lan  - 7:4.15-7.5
+- Fix squid: Denial of Service in SSL Certificate validation (CVE-2023-46724)
+- Fix squid: NULL pointer dereference in the gopher protocol code (CVE-2023-46728)
+- Fix squid: Buffer over-read in the HTTP Message processing feature (CVE-2023-49285)
+- Fix squid: Incorrect Check of Function Return Value In Helper Process management(CVE-2023-49286)
+
 * Sun Dec 09 2023 Alex Burmashev  - 7:4.15-7.3
 - Fix squid: DoS against HTTP and HTTPS (CVE-2023-5824)