]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Remove cachemgr.cgi tool (#1542)
authorAmos Jeffries <yadij@users.noreply.github.com>
Sun, 29 Oct 2023 19:17:22 +0000 (19:17 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Sun, 29 Oct 2023 19:17:35 +0000 (19:17 +0000)
14 files changed:
INSTALL
configure.ac
doc/Programming-Guide/03_MajorComponents.dox
doc/release-notes/release-7.sgml.in
include/squid.h
src/cf.data.pre
src/squid.8.in
test-suite/buildtests/layer-01-minimal.opts
test-suite/buildtests/layer-02-maximus.opts
test-suite/buildtests/layer-04-noauth-everything.opts
tools/Makefile.am
tools/cachemgr.cc [deleted file]
tools/cachemgr.cgi.8.in [deleted file]
tools/cachemgr.conf [deleted file]

diff --git a/INSTALL b/INSTALL
index 7353df9de6751eaa647318adeb0505b694f0bcfb..da2f34cd4ab482a13ca00c954c28dd71eef476e6 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -22,7 +22,3 @@ To run a Cache, you will need to:
              
        3. start the cache:
              % /usr/local/squid/sbin/squid
-
-If you want to use the WWW interface to the Cache Manager, copy
-the tools/cachemgr.cgi program into your httpd server's cgi-bin
-directory.
index 389206c8bcc1d9dcafa36e195059dd032627abb0..5e5939526ab7f9cc20c27e158e2142219e0e7935 100644 (file)
@@ -993,23 +993,6 @@ AS_IF([test "x$enable_snmp" = "xyes"],[SNMPLIB="../lib/snmplib/libsnmplib.la"])
 AC_MSG_NOTICE([SNMP support enabled: $enable_snmp])
 AC_SUBST(SNMPLIB)
 
-AC_ARG_ENABLE(cachemgr-hostname,
-  AS_HELP_STRING([--enable-cachemgr-hostname=hostname],
-                 [Make cachemgr.cgi default to this host.
-                  If unspecified, uses the name of the build-host]), [
-  AS_CASE([$enableval],
-    [yes],[
-      AC_DEFINE(CACHEMGR_HOSTNAME,[getfullhostname()],
-        [If you are upset that the cachemgr.cgi form comes up with the hostname field blank, then define this to getfullhostname()])
-      AC_MSG_NOTICE([Cachemgr default hostname == host where cachemgr runs])
-    ],
-    [no],[:],
-    [
-      AC_DEFINE_UNQUOTED(CACHEMGR_HOSTNAME,"${enableval}")
-      AC_MSG_NOTICE([Cachemgr default hostname set to ${enableval}])
-  ])
-])
-
 AC_ARG_ENABLE(eui,
   AS_HELP_STRING([--disable-eui],
                  [Disable use of ARP / MAC/ EUI (ether address)]), [
index c3d13bf2099abc061a28408f610df958dcaa1bc7..436a08be6323040b548b1102a074a31ae003c58b 100644 (file)
@@ -143,17 +143,14 @@ TODO: decide what to do for comm_poll() since its either obsolete or uses other
 \section CacheManager Cache Manager
 \par
        This provides access to certain information needed by the
-       cache administrator.  A companion program, cachemgr.cgi
-       can be used to make this information available via a Web
-       browser.  Cache manager requests to Squid are made with a
-       special URL of the form
+       cache administrator. Cache manager requests to Squid are
+       made with a special URL of the form
 \code
-       cache_object://hostname/operation
+       http://hostname:3128/squid-internal-mgr/menu
 \endcode
        The cache manager provides essentially "read-only" access
        to information.  It does not provide a method for configuring
        Squid while it is running.
-TODO: get cachemgr.cgi documenting
 
 \section NetworkMeasurementDB Network Measurement Database
 \par
index 60e43ba7860f805590b4be0f291a11bdbc7122e5..8ed6306c9c0ed6bf7159d6b725379718ac4a7a20 100644 (file)
@@ -30,7 +30,6 @@ The Squid-@SQUID_RELEASE@ change history can be <url url="https://github.com/squ
 
 <p>The most important of these new features are:
 <itemize>
-       <item>removed support for the cache_object URI scheme
        <item>Cache Manager changes
        <item>Removed purge tool
 </itemize>
@@ -40,23 +39,28 @@ The Squid-@SQUID_RELEASE@ change history can be <url url="https://github.com/squ
 <sect1>Cache Manager changes<label id="mgr">
 <p>For more information about the Cache Manager feature, see <url url="https://wiki.squid-cache.org/Features/CacheManager/Index" name="wiki">.
 
-<p>
-<descrip>
-       <tag>cache_object URI</tag>
-       <p>Cache manager is no longer accessible by URIs with cache_object scheme.
+<p>In order to reduce workload on the Squid development team we have chosen to stop
+   providing several tools related to Cache Manager which have previously been
+   bundled with Squid.
 
-    <tag>cachemgr</tag>
-    <p>The 'cachemgr' tool is no longer supported and distributed with squid.
-    A plethora of tools, such as curl, wget, or any web browser,
-    can be used in its place
+<sect2>Removal of the <em>squidclient</em> tool.
+<p>Popular command-line tools such as <em>curl</em> or <em>wget</em>
+   provide equivalent features.
 
-       <tag>non_peers</tag>
-       <p>Removed the <em>mgr:non_peers</em> report. Squid still ignores
-       unexpected ICP responses but no longer remembers the details that comprised
-       the removed report. The senders of these ICP messages are still reported to
-       cache.log at debugging level 1 (with an exponential backoff).
+<sect2>Removal of the <em>cachemgr.cgi</em> tool.
+<p>Access to the Cache Manager API is available by sending HTTP(S) requests
+   directly to Squid with the URL-path prefix <em>/squid-internal-mgr/</em>.
+   A plethora of tools, such as curl, wget, or any web browser, can be used
+   instead of cachemgr.cgi.
 
-</descrip>
+<sect2>Removal of the <em>cache_object:</em> URI scheme.
+<p>This custom scheme does not conform to RFC 3986 URI sytax. It has been replaced
+   with Cache Manager access through HTTP and HTTPS URLs.
+
+<sect2>Removal of <em>non_peers</em> Report
+<p>Squid still ignores unexpected ICP responses but no longer remembers the
+   details that comprised the removed report. The senders of these ICP messages
+   are still reported to cache.log at debugging level 1 (with an exponential backoff).
 
 <sect1>Removed purge tool
 <p>The <em>purge</em> tool (also known as <em>squidpurge</em>, and <em>squid-purge</em>)
@@ -160,6 +164,9 @@ This section gives an account of those changes in three categories:
 <sect1>Removed options<label id="removedoptions">
 <p>
 <descrip>
+       <tag>--enable-cachemgr-hostname=</tag>
+       <p>The <em>cachemgr.cgi</em> tool this option relates to has been removed.
+
        <tag>CPPFLAGS=-DHEADERS_LOG</tag>
        <p>The code enabled by this preprocessor macro has not built for many
           years, indicating that the feature is unused.
index 6240a6c574ae1eec4e4bc413930ffc5441f3cff7..3b05f69965b300f5f017ab51ca525fa3fa506ceb 100644 (file)
 #endif
 #endif
 
-#if !defined(CACHEMGR_HOSTNAME)
-#define CACHEMGR_HOSTNAME ""
-#else
-#define CACHEMGR_HOSTNAME_DEFINED 1
-#endif
-
 #if SQUID_DETECT_UDP_SO_SNDBUF > 16384
 #define SQUID_UDP_SO_SNDBUF 16384
 #else
index 117ca0d157366e98408445e37fb949627d9f06e3..a89022cc4d0c6d95f817b734a74899f6d5fa60dc 100644 (file)
@@ -7536,8 +7536,8 @@ LOC: Config.onoff.httpd_suppress_version_string
 DOC_START
        Do not send Squid version string in HTTP metadata and generated content
        such as HTML error pages. Squid version string is still present in certain
-       SNMP responses, cachemgr.cgi output, squidclient User-Agent request header
-       field, various console output, and cache.log.
+       SNMP responses, HTTP(S) Server response header field,
+        various console output, and cache.log.
 DOC_END
 
 NAME: visible_hostname
index e460e34cd392e1c6be8fc132ad152c0ffccd7db9..c8c76cebf59c624bb5be08516a2a61ffb8e81393 100644 (file)
@@ -222,11 +222,6 @@ your build of Squid. The online configuration manual is also available for
 a full reference of options.
 .BR see http://www.squid-cache.org/Doc/config/
 .
-.if !'po4a'hide' .IP "cachemgr.conf"
-The main configuration file for the web
-.B cachemgr.cgi
-tools.
-.
 .if !'po4a'hide' .IP "msntauth.conf"
 The main configuration file for the Sample MSNT authenticator.
 .
@@ -281,7 +276,6 @@ Report ideas for new improvements to the
 .if !'po4a'hide' <squid-dev@lists.squid-cache.org>
 .
 .SH SEE ALSO
-.if !'po4a'hide' .B cachemgr.cgi "(8), "
 .if !'po4a'hide' .B basic_pam_auth "(8), "
 .if !'po4a'hide' .B basic_ldap_auth "(8), "
 .if !'po4a'hide' .B ext_ldap_group_acl "(8), "
index d0203436f6b04e2075981daac5db32961b6e2a79..12ced1ea1dc91eee6e574e200bcacd9dccbbfa12 100644 (file)
@@ -51,7 +51,6 @@ DISTCHECK_CONFIGURE_FLAGS=" \
        --disable-wccp \
        --disable-wccpv2 \
        --disable-snmp \
-       --disable-cachemgr-hostname \
        --disable-eui \
        --disable-htcp \
        --disable-ssl-crtd \
index 374afdcbd78423da0213338b9c0ae1ecc3ded0d5..03277b2642d47ac66e44ebbe004aad1470f824b6 100644 (file)
@@ -72,7 +72,6 @@ DISTCHECK_CONFIGURE_FLAGS=" \
        --enable-wccp \
        --enable-wccpv2 \
        --enable-snmp \
-       --enable-cachemgr-hostname \
        --enable-eui \
        --enable-htcp \
        --enable-forw-via-db \
index bdb1723a08d97f36713b98bc29ae8cc664a6ceb8..9119a2a90e563e8186a84ae6bfa0e8d36c9d5978 100644 (file)
@@ -72,7 +72,6 @@ DISTCHECK_CONFIGURE_FLAGS=" \
        --enable-wccp \
        --enable-wccpv2 \
        --enable-snmp \
-       --enable-cachemgr-hostname \
        --enable-eui \
        --enable-htcp \
        --enable-ssl \
index e1cc645684db658723373786a4d742e073f516ec..dc09ace40eb400e9a115cffb7635aab97d27bf9c 100644 (file)
@@ -5,106 +5,5 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-include $(top_srcdir)/src/Common.am
-
-## we need our local files too (but avoid -I. at all costs)
-AM_CPPFLAGS += -I$(srcdir)
-
-SUBDIRS= apparmor helper-mux systemd sysvinit
-EXTRA_DIST=
-man_MANS=
-DISTCLEANFILES=
-
-LDADD= \
-       $(top_builddir)/src/html/libhtml.la \
-       $(top_builddir)/src/ip/libip.la \
-       $(top_builddir)/src/mem/libminimal.la \
-       $(top_builddir)/src/time/libtime.la \
-       $(top_builddir)/lib/libmiscencoding.la \
-       $(top_builddir)/lib/libmiscutil.la \
-       $(COMPAT_LIB) \
-       $(LIBNETTLE_LIBS) \
-       $(KRB5LIBS) \
-       $(XTRA_LIBS)
-
-include $(top_srcdir)/doc/manuals/Substitute.am
-
-## Several files need to be shared but we cannot depend on the other
-## directories to be built.
-test_tools.cc: $(top_srcdir)/test-suite/test_tools.cc
-       cp $(top_srcdir)/test-suite/test_tools.cc $@
-
-tests/stub_debug.cc: $(top_srcdir)/src/tests/stub_debug.cc | tests
-       cp $(top_srcdir)/src/tests/stub_debug.cc $@
-
-Here.cc: $(top_srcdir)/src/base/Here.cc
-       cp $(top_srcdir)/src/base/Here.cc $@
-
-CharacterSet.cc: $(top_srcdir)/src/base/CharacterSet.cc
-       cp $(top_srcdir)/src/base/CharacterSet.cc $@
-
-MemBuf.cc: $(top_srcdir)/src/MemBuf.cc
-       cp $(top_srcdir)/src/MemBuf.cc $@
-
-tests/stub_cbdata.cc: $(top_srcdir)/src/tests/stub_cbdata.cc | tests
-       cp $(top_srcdir)/src/tests/stub_cbdata.cc $@
-
-tests/STUB.h: $(top_srcdir)/src/tests/STUB.h | tests
-       cp $(top_srcdir)/src/tests/STUB.h $@
-
-tests:
-       mkdir -p $@
-
-# stock tools for unit tests - library independent versions of dlink_list
-# etc.
-# globals.cc is needed by test_tools.cc.
-# Neither of these should be disted from here.
-TESTSOURCES= test_tools.cc
-CLEANFILES += test_tools.cc Here.cc CharacterSet.cc MemBuf.cc tests/stub_debug.cc tests/stub_cbdata.cc tests/STUB.h
-
-## Test Scripts
-EXTRA_DIST += helper-ok-dying.pl helper-ok.pl
-
-## ##### cachemgr.cgi  #####
-
-DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/cachemgr.conf
-
-libexec_PROGRAMS = cachemgr$(CGIEXT)
-
-cachemgr__CGIEXT__SOURCES = \
-       CharacterSet.cc \
-       Here.cc \
-       MemBuf.cc \
-       cachemgr.cc \
-       test_tools.cc
-
-nodist_cachemgr__CGIEXT__SOURCES = \
-       tests/stub_cbdata.cc \
-       tests/stub_debug.cc \
-       tests/STUB.h
-
-cachemgr__CGIEXT__CXXFLAGS = \
-       $(AM_CXXFLAGS) \
-       -DDEFAULT_CACHEMGR_CONFIG=\"$(DEFAULT_CACHEMGR_CONFIG)\"
-
-EXTRA_DIST += cachemgr.conf cachemgr.cgi.8 cachemgr.cgi.8.in
-CLEANFILES += cachemgr.cgi.8
-man_MANS += cachemgr.cgi.8
-
-cachemgr.cgi.8: $(srcdir)/cachemgr.cgi.8.in Makefile
-       $(SUBSTITUTE) < $(srcdir)/cachemgr.cgi.8.in > $@
-
-## Shared
-
-install-data-local:
-       $(INSTALL_DATA) $(srcdir)/cachemgr.conf $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG).default
-       @if test -f $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG) ; then \
-               echo "$@ will not overwrite existing $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG)" ; \
-       else \
-               echo "$(INSTALL_DATA) $(srcdir)/cachemgr.conf $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG)"; \
-               $(INSTALL_DATA) $(srcdir)/cachemgr.conf $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG); \
-       fi
-
-uninstall-local:
-       @$(SHELL) $(top_srcdir)/scripts/remove-cfg.sh "$(RM)" $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG)
-       $(RM) -f $(DESTDIR)$(DEFAULT_CACHEMGR_CONFIG).default
+SUBDIRS = apparmor helper-mux systemd sysvinit
+EXTRA_DIST = helper-ok-dying.pl helper-ok.pl
diff --git a/tools/cachemgr.cc b/tools/cachemgr.cc
deleted file mode 100644 (file)
index 928c59e..0000000
+++ /dev/null
@@ -1,1323 +0,0 @@
-/*
- * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-#include "base/CharacterSet.h"
-#include "base64.h"
-#include "getfullhostname.h"
-#include "html/Quoting.h"
-#include "ip/Address.h"
-#include "MemBuf.h"
-#include "rfc1738.h"
-#include "time/gadgets.h"
-#include "util.h"
-
-#include <cctype>
-#include <cerrno>
-#include <csignal>
-#include <cstring>
-#include <ctime>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_GRP_H
-#include <grp.h>
-#endif
-#if HAVE_GNUMALLOC_H
-#include <gnumalloc.h>
-#elif HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#if HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#if HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if HAVE_PWD_H
-#include <pwd.h>
-#endif
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#if HAVE_LIBC_H
-#include <libc.h>
-#endif
-#if HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#if HAVE_BSTRING_H
-#include <bstring.h>
-#endif
-#if HAVE_CRYPT_H
-#include <crypt.h>
-#endif
-#if HAVE_FNMATCH_H
-extern "C" {
-#include <fnmatch.h>
-}
-#endif
-
-#ifndef DEFAULT_CACHEMGR_CONFIG
-#define DEFAULT_CACHEMGR_CONFIG "/etc/squid/cachemgr.conf"
-#endif
-
-typedef struct {
-    char *server;
-    char *hostname;
-    int port;
-    char *action;
-    char *user_name;
-    char *passwd;
-    char *pub_auth;
-    char *workers;
-    char *processes;
-} cachemgr_request;
-
-/*
- * Static variables and constants
- */
-static const time_t passwd_ttl = 60 * 60 * 3;   /* in sec */
-static const char *script_name = "/cgi-bin/cachemgr.cgi";
-static const char *progname = nullptr;
-static time_t now;
-
-/*
- * Function prototypes
- */
-static const char *safe_str(const char *str);
-static const char *xstrtok(char **str, char del);
-static void print_trailer(void);
-static void auth_html(const char *host, int port, const char *user_name);
-static void error_html(const char *msg);
-static char *menu_url(cachemgr_request * req, const char *action);
-static int parse_status_line(const char *sline, const char **statusStr);
-static cachemgr_request *read_request(void);
-static char *read_get_request(void);
-static char *read_post_request(void);
-
-static void make_pub_auth(cachemgr_request * req);
-static void decode_pub_auth(cachemgr_request * req);
-static void reset_auth(cachemgr_request * req);
-static const char *make_auth_header(const cachemgr_request * req);
-
-static int check_target_acl(const char *hostname, int port);
-
-#if _SQUID_WINDOWS_
-static int s_iInitCount = 0;
-
-int Win32SockInit(void)
-{
-    int iVersionRequested;
-    WSADATA wsaData;
-    int err;
-
-    if (s_iInitCount > 0) {
-        ++s_iInitCount;
-        return (0);
-    } else if (s_iInitCount < 0)
-        return (s_iInitCount);
-
-    /* s_iInitCount == 0. Do the initialization */
-    iVersionRequested = MAKEWORD(2, 0);
-
-    err = WSAStartup((WORD) iVersionRequested, &wsaData);
-
-    if (err) {
-        s_iInitCount = -1;
-        return (s_iInitCount);
-    }
-
-    if (LOBYTE(wsaData.wVersion) != 2 ||
-            HIBYTE(wsaData.wVersion) != 0) {
-        s_iInitCount = -2;
-        WSACleanup();
-        return (s_iInitCount);
-    }
-
-    ++s_iInitCount;
-    return (s_iInitCount);
-}
-
-void Win32SockCleanup(void)
-{
-    if (--s_iInitCount == 0)
-        WSACleanup();
-
-    return;
-}
-
-#endif
-
-static const char *
-safe_str(const char *str)
-{
-    return str ? str : "";
-}
-
-/* relaxed number format */
-static int
-is_number(const char *str)
-{
-    return strspn(str, "\t -+01234567890./\n") == strlen(str);
-}
-
-static const char *
-xstrtok(char **str, char del)
-{
-    if (*str) {
-        char *p = strchr(*str, del);
-        char *tok = *str;
-        int len;
-
-        if (p) {
-            *str = p + 1;
-            *p = '\0';
-        } else
-            *str = nullptr;
-
-        /* trim */
-        len = strlen(tok);
-
-        while (len && xisspace(tok[len - 1]))
-            tok[--len] = '\0';
-
-        while (xisspace(*tok))
-            ++tok;
-
-        return tok;
-    } else
-        return "";
-}
-
-static bool
-hostname_check(const char *uri)
-{
-    static CharacterSet hostChars = CharacterSet("host",".:[]_") +
-                                    CharacterSet::ALPHA + CharacterSet::DIGIT;
-
-    const auto limit = strlen(uri);
-    for (size_t i = 0; i < limit; i++) {
-        if (!hostChars[uri[i]]) {
-            return false;
-        }
-    }
-    return true;
-}
-
-static void
-print_trailer(void)
-{
-    printf("<HR noshade size=\"1px\">\n");
-    printf("<ADDRESS>\n");
-    printf("Generated %s, by %s/%s@%s\n",
-           Time::FormatRfc1123(now), progname, VERSION, getfullhostname());
-    printf("</ADDRESS></BODY></HTML>\n");
-}
-
-static void
-auth_html(const char *host, int port, const char *user_name)
-{
-    FILE *fp;
-    int need_host = 1;
-
-    if (!user_name)
-        user_name = "";
-
-    if (!host || !strlen(host))
-        host = "";
-
-    fp = fopen("cachemgr.conf", "r");
-
-    if (fp == nullptr)
-        fp = fopen(DEFAULT_CACHEMGR_CONFIG, "r");
-
-    if (fp == nullptr)
-        printf("X-Error: message=\"Unable to open config %s\"", DEFAULT_CACHEMGR_CONFIG);
-
-    printf("Content-Type: text/html\r\n\r\n");
-
-    printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
-
-    printf("<HTML><HEAD><TITLE>Cache Manager Interface</TITLE>\n");
-
-    printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n");
-
-    printf("<script type=\"text/javascript\">\n");
-    printf("function TS(t, s) {\n");
-    printf(" var x = new XMLHttpRequest();\n");
-    printf(" x.open('GET', 'http' + s + '://' + t + '/squid-internal-mgr/', true);\n");
-    printf(" x.onreadystatechange=function() {\n");
-    printf("  if (x.readyState==4) {\n");
-    printf("   if ((x.status>=200 && x.status <= 299) || x.status==401) {\n");
-    printf("    var v = x.getResponseHeader('Server');\n");
-    printf("    if (v.substring(0,6) == 'squid/' || v == 'squid') {\n");
-    printf("     var d = document.getElementById('H' + s + 'mgr');\n");
-    printf("     if (d.innerHTML == '') d.innerHTML = '<h2>HTTP' + (s=='s'?'S':'') + ' Managed Proxies</h2>';\n");
-    printf("     d.innerHTML = d.innerHTML + '<p>Host: <a href=\"http' + s + '://' + t + '/squid-internal-mgr/\">' + t + '</a></p>';\n");
-    printf("     var sv = document.getElementById('server');\n");
-    printf("     var op = sv.getElementsByTagName('OPTION');\n");
-    printf("     for(var i=0; i<op.length; i++) { if (op[i].innerHTML == t) { sv.removeChild(op[i]); i--; }}\n");
-    printf("     if (sv.getElementsByTagName('OPTION').length == 0) {\n");
-    printf("      document.getElementById('Cmgr').innerHTML = '';\n");
-    printf(" }}}}}\n");
-    printf(" x.send(null);\n");
-    printf("}\n");
-    printf("</script>\n");
-
-    printf("</HEAD>\n");
-
-    printf("<BODY><H1>Cache Manager Interface</H1>\n");
-
-    printf("<P>This is a WWW interface to the instrumentation interface\n");
-
-    printf("for the Squid object cache.</P>\n");
-
-    printf("<HR noshade size=\"1px\">\n");
-
-    printf("<div id=\"Hsmgr\"></div>\n");
-    printf("<div id=\"Hmgr\"></div>\n");
-    printf("<div id=\"Cmgr\">\n");
-    printf("<h2>CGI Managed Proxies</h2>\n");
-    printf("<FORM METHOD=\"POST\" ACTION=\"%s\">\n", script_name);
-
-    printf("<TABLE BORDER=\"0\" CELLPADDING=\"10\" CELLSPACING=\"1\">\n");
-
-    if (fp != nullptr) {
-        int servers = 0;
-        char config_line[BUFSIZ];
-
-        while (fgets(config_line, BUFSIZ, fp)) {
-            char *server, *comment;
-            if (strtok(config_line, "\r\n") == nullptr)
-                continue;
-
-            if (config_line[0] == '#')
-                continue;
-
-            if (config_line[0] == '\0')
-                continue;
-
-            if ((server = strtok(config_line, " \t")) == nullptr)
-                continue;
-
-            if (strchr(server, '*') || strchr(server, '[') || strchr(server, '?')) {
-                need_host = -1;
-                continue;
-            }
-
-            comment = strtok(nullptr, "");
-
-            if (comment)
-                while (*comment == ' ' || *comment == '\t')
-                    ++comment;
-
-            if (!comment || !*comment)
-                comment = server;
-
-            if (!servers)
-                printf("<TR><TH ALIGN=\"left\">Cache Server:</TH><TD><SELECT id=\"server\" NAME=\"server\">\n");
-
-            printf("<OPTION VALUE=\"%s\"%s>%s</OPTION>\n", server, (servers || *host) ? "" : " SELECTED", comment);
-            ++servers;
-        }
-
-        if (servers) {
-            if (need_host == 1 && !*host)
-                need_host = 0;
-
-            if (need_host)
-                printf("<OPTION VALUE=\"\"%s>Other</OPTION>\n", (*host) ? " SELECTED" : "");
-
-            printf("</SELECT></TR>\n");
-        }
-
-        fclose(fp);
-    }
-
-    if (need_host) {
-        if (need_host == 1 && !*host)
-            host = "localhost";
-
-        printf("<TR><TH ALIGN=\"left\">Cache Host:</TH><TD><INPUT NAME=\"host\" ");
-
-        printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", host);
-
-        printf("<TR><TH ALIGN=\"left\">Cache Port:</TH><TD><INPUT NAME=\"port\" ");
-
-        printf("size=\"30\" VALUE=\"%d\"></TD></TR>\n", port);
-    }
-
-    printf("<TR><TH ALIGN=\"left\">Manager name:</TH><TD><INPUT NAME=\"user_name\" ");
-
-    printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", rfc1738_escape(user_name));
-
-    printf("<TR><TH ALIGN=\"left\">Password:</TH><TD><INPUT TYPE=\"password\" NAME=\"passwd\" ");
-
-    printf("size=\"30\" VALUE=\"\"></TD></TR>\n");
-
-    printf("</TABLE><BR CLEAR=\"all\">\n");
-
-    printf("<INPUT TYPE=\"submit\" VALUE=\"Continue...\">\n");
-
-    printf("</FORM></div>\n");
-
-    printf("<script type=\"text/javascript\">\n");
-    printf("var s = document.getElementById(\"server\");\n");
-    printf("for (var i = 0; i < s.childElementCount; i++) {\n");
-    printf(" TS(s.children[i].value, '');\n");
-    printf(" TS(s.children[i].value, 's');\n");
-    printf("}</script>\n");
-
-    print_trailer();
-}
-
-static void
-error_html(const char *msg)
-{
-    printf("Content-Type: text/html\r\n\r\n");
-    printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
-    printf("<HTML><HEAD><TITLE>Cache Manager Error</TITLE>\n");
-    printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE></HEAD>\n");
-    printf("<BODY><H1>Cache Manager Error</H1>\n");
-    printf("<P>\n%s</P>\n", html_quote(msg));
-    print_trailer();
-}
-
-/* returns http status extracted from status line or -1 on parsing failure */
-static int
-parse_status_line(const char *sline, const char **statusStr)
-{
-    const char *sp = strchr(sline, ' ');
-
-    if (statusStr)
-        *statusStr = nullptr;
-
-    if (strncasecmp(sline, "HTTP/", 5) || !sp)
-        return -1;
-
-    while (xisspace(*++sp));
-    if (!xisdigit(*sp))
-        return -1;
-
-    if (statusStr)
-        *statusStr = sp;
-
-    return atoi(sp);
-}
-
-static char *
-menu_url(cachemgr_request * req, const char *action)
-{
-    static char url[1024];
-    snprintf(url, sizeof(url), "%s?host=%s&port=%d&user_name=%s&operation=%s&auth=%s",
-             script_name,
-             req->hostname,
-             req->port,
-             rfc1738_escape(safe_str(req->user_name)),
-             action,
-             safe_str(req->pub_auth));
-    return url;
-}
-
-static void
-munge_menu_line(MemBuf &out, const char *buf, cachemgr_request * req)
-{
-    char *x;
-    const char *a;
-    const char *d;
-    const char *p;
-    char *a_url;
-    char *buf_copy;
-
-    const auto bufLen = strlen(buf);
-    if (bufLen < 1)
-        return; // nothing to append
-
-    if (*buf != ' ') {
-        out.append(buf, bufLen);
-        return;
-    }
-
-    buf_copy = x = xstrndup(buf, bufLen+1);
-
-    a = xstrtok(&x, '\t');
-
-    d = xstrtok(&x, '\t');
-
-    p = xstrtok(&x, '\t');
-
-    a_url = xstrdup(menu_url(req, a));
-
-    /* no reason to give a url for a disabled action */
-    if (!strcmp(p, "disabled"))
-        out.appendf("<LI type=\"circle\">%s (disabled)<A HREF=\"%s\">.</A>\n", d, a_url);
-    else
-        /* disable a hidden action (requires a password, but password is not in squid.conf) */
-        if (!strcmp(p, "hidden"))
-            out.appendf("<LI type=\"circle\">%s (hidden)<A HREF=\"%s\">.</A>\n", d, a_url);
-        else
-            /* disable link if authentication is required and we have no password */
-            if (!strcmp(p, "protected") && !req->passwd)
-                out.appendf("<LI type=\"circle\">%s (requires <a href=\"%s\">authentication</a>)<A HREF=\"%s\">.</A>\n",
-                            d, menu_url(req, "authenticate"), a_url);
-            else
-                /* highlight protected but probably available entries */
-                if (!strcmp(p, "protected"))
-                    out.appendf("<LI type=\"square\"><A HREF=\"%s\"><font color=\"#FF0000\">%s</font></A>\n",
-                                a_url, d);
-
-    /* public entry or unknown type of protection */
-                else
-                    out.appendf("<LI type=\"disk\"><A HREF=\"%s\">%s</A>\n", a_url, d);
-
-    xfree(a_url);
-
-    xfree(buf_copy);
-}
-
-static void
-munge_other_line(MemBuf &out, const char *buf, cachemgr_request *)
-{
-    static const char *ttags[] = {"td", "th"};
-
-    static int table_line_num = 0;
-    static int next_is_header = 0;
-    int is_header = 0;
-    const char *ttag;
-    char *buf_copy;
-    char *x, *p;
-    /* does it look like a table? */
-
-    if (!strchr(buf, '\t') || *buf == '\t') {
-        /* nope, just text */
-        if (table_line_num)
-            out.append("</table>\n<pre>", 14);
-        out.appendf("%s", html_quote(buf));
-        table_line_num = 0;
-        return;
-    }
-
-    /* start html table */
-    if (!table_line_num) {
-        out.append("</pre><table cellpadding=\"2\" cellspacing=\"1\">\n", 46);
-        next_is_header = 0;
-    }
-
-    /* remove '\n' */
-    is_header = (!table_line_num || next_is_header) && !strchr(buf, ':') && !is_number(buf);
-
-    ttag = ttags[is_header];
-
-    /* record starts */
-    out.append("<tr>", 4);
-
-    /* substitute '\t' */
-    buf_copy = x = xstrdup(buf);
-
-    if ((p = strchr(x, '\n')))
-        *p = '\0';
-
-    while (x && strlen(x)) {
-        int column_span = 1;
-        const char *cell = xstrtok(&x, '\t');
-
-        while (x && *x == '\t') {
-            ++column_span;
-            ++x;
-        }
-
-        out.appendf("<%s colspan=\"%d\" align=\"%s\">%s</%s>",
-                    ttag, column_span,
-                    is_header ? "center" : is_number(cell) ? "right" : "left",
-                    html_quote(cell), ttag);
-    }
-
-    xfree(buf_copy);
-    /* record ends */
-    out.append("</tr>\n", 6);
-    next_is_header = is_header && strstr(buf, "\t\t");
-    ++table_line_num;
-}
-
-static const char *
-munge_action_line(const char *_buf, cachemgr_request * req)
-{
-    static char html[2 * 1024];
-    char *buf = xstrdup(_buf);
-    char *x = buf;
-    const char *action, *description;
-    char *p;
-
-    if ((p = strchr(x, '\n')))
-        *p = '\0';
-    action = xstrtok(&x, '\t');
-    if (!action) {
-        xfree(buf);
-        return "";
-    }
-    description = xstrtok(&x, '\t');
-    if (!description)
-        description = action;
-    snprintf(html, sizeof(html), " <a href=\"%s\">%s</a>", menu_url(req, action), description);
-    xfree(buf);
-    return html;
-}
-
-static int
-read_reply(int s, cachemgr_request * req)
-{
-    char buf[4 * 1024];
-#if _SQUID_WINDOWS_
-
-    int reply;
-    char *tmpfile = tempnam(nullptr, "tmp0000");
-    FILE *fp = fopen(tmpfile, "w+");
-#else
-
-    FILE *fp = fdopen(s, "r");
-#endif
-    /* interpretation states */
-    enum {
-        isStatusLine, isHeaders, isActions, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError
-    } istate = isStatusLine;
-    int parse_menu = 0;
-    const char *action = req->action;
-    const char *statusStr = nullptr;
-    int status = -1;
-
-    if (0 == strlen(req->action))
-        parse_menu = 1;
-    else if (0 == strcasecmp(req->action, "menu"))
-        parse_menu = 1;
-
-    if (fp == nullptr) {
-#if _SQUID_WINDOWS_
-        perror(tmpfile);
-        xfree(tmpfile);
-#else
-
-        perror("fdopen");
-#endif
-
-        close(s);
-        return 1;
-    }
-
-#if _SQUID_WINDOWS_
-
-    while ((reply=recv(s, buf, sizeof(buf), 0)) > 0)
-        fwrite(buf, 1, reply, fp);
-
-    rewind(fp);
-
-#endif
-
-    if (parse_menu)
-        action = "menu";
-
-    /* read reply interpreting one line at a time depending on state */
-    while (istate < isEof) {
-        if (!fgets(buf, sizeof(buf), fp))
-            istate = istate == isForward ? isForwardEof : isEof;
-
-        switch (istate) {
-
-        case isStatusLine:
-            /* get HTTP status */
-            /* uncomment the following if you want to debug headers */
-            /* fputs("\r\n\r\n", stdout); */
-            status = parse_status_line(buf, &statusStr);
-            istate = status == 200 ? isHeaders : isForward;
-            /* if cache asks for authentication, we have to reset our info */
-
-            if (status == 401 || status == 407) {
-                reset_auth(req);
-                status = 403;   /* Forbidden, see comments in case isForward: */
-            }
-
-            /* this is a way to pass HTTP status to the Web server */
-            if (statusStr)
-                printf("Status: %d %s", status, statusStr); /* statusStr has '\n' */
-
-            break;
-
-        case isHeaders:
-            /* forward header field */
-            if (!strcmp(buf, "\r\n")) {     /* end of headers */
-                fputs("Content-Type: text/html\r\n", stdout);   /* add our type */
-                istate = isBodyStart;
-            }
-
-            if (strncasecmp(buf, "Content-Type:", 13))  /* filter out their type */
-                fputs(buf, stdout);
-
-            break;
-
-        case isBodyStart:
-            printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
-
-            printf("<HTML><HEAD><TITLE>CacheMgr@%s: %s</TITLE>\n",
-                   req->hostname, action);
-
-            printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}TABLE{background-color:#333333;border:0pt;padding:0pt}TH,TD{background-color:#ffffff;white-space:nowrap}--></STYLE>\n");
-
-            printf("</HEAD><BODY>\n");
-
-            if (parse_menu) {
-                printf("<H2><a href=\"%s\">Cache Manager</a> menu for %s:</H2>",
-                       menu_url(req, "authenticate"), req->hostname);
-                printf("<UL>\n");
-            } else {
-                printf("<P><A HREF=\"%s\">%s</A>\n<HR noshade size=\"1px\">\n",
-                       menu_url(req, "menu"), "Cache Manager menu");
-                printf("<PRE>\n");
-            }
-
-            istate = isActions;
-            [[fallthrough]]; // we do not want to lose the first line
-
-        case isActions:
-            if (strncmp(buf, "action:", 7) == 0) {
-                fputs(" ", stdout);
-                fputs(munge_action_line(buf + 7, req), stdout);
-                break;
-            }
-            if (parse_menu) {
-                printf("<UL>\n");
-            } else {
-                printf("<HR noshade size=\"1px\">\n");
-                printf("<PRE>\n");
-            }
-
-            istate = isBody;
-            [[fallthrough]]; // we do not want to lose the first line
-
-        case isBody:
-        {
-            /* interpret [and reformat] cache response */
-            MemBuf out;
-            out.init();
-            if (parse_menu)
-                munge_menu_line(out, buf, req);
-            else
-                munge_other_line(out, buf, req);
-
-            fputs(out.buf, stdout);
-        }
-        break;
-
-        case isForward:
-            /* forward: no modifications allowed */
-            /*
-             * Note: we currently do not know any way to get browser.reply to
-             * 401 to .cgi because web server filters out all auth info. Thus we
-             * disable authentication headers for now.
-             */
-            if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));    /* skip */
-            else
-                fputs(buf, stdout);
-
-            break;
-
-        case isEof:
-            /* print trailers */
-            if (parse_menu)
-                printf("</UL>\n");
-            else
-                printf("</table></PRE>\n");
-
-            print_trailer();
-
-            istate = isSuccess;
-
-            break;
-
-        case isForwardEof:
-            /* indicate that we finished processing an "error" sequence */
-            istate = isError;
-
-            break;
-
-        default:
-            printf("%s: internal bug: invalid state reached: %d", script_name, istate);
-
-            istate = isError;
-        }
-    }
-
-    fclose(fp);
-#if _SQUID_WINDOWS_
-
-    remove(tmpfile);
-    xfree(tmpfile);
-    close(s);
-
-#endif
-
-    return 0;
-}
-
-static int
-process_request(cachemgr_request * req)
-{
-
-    char ipbuf[MAX_IPSTRLEN];
-    struct addrinfo *AI = nullptr;
-    Ip::Address S;
-    int s;
-    int l;
-
-    static char buf[2 * 1024];
-
-    if (req == nullptr) {
-        auth_html(CACHEMGR_HOSTNAME, CACHE_HTTP_PORT, "");
-        return 1;
-    }
-
-    if (req->hostname == nullptr) {
-        req->hostname = xstrdup(CACHEMGR_HOSTNAME);
-    }
-
-    if (req->port == 0) {
-        req->port = CACHE_HTTP_PORT;
-    }
-
-    if (req->action == nullptr) {
-        req->action = xstrdup("menu");
-    }
-
-    if (strcmp(req->action, "authenticate") == 0) {
-        auth_html(req->hostname, req->port, req->user_name);
-        return 0;
-    }
-
-    if (!check_target_acl(req->hostname, req->port)) {
-        snprintf(buf, sizeof(buf), "target %s:%d not allowed in cachemgr.conf\n", req->hostname, req->port);
-        error_html(buf);
-        return 1;
-    }
-
-    S = *gethostbyname(req->hostname);
-
-    if ( !S.isAnyAddr() ) {
-        (void) 0;
-    } else if ((S = req->hostname))
-        (void) 0;
-    else {
-        if (hostname_check(req->hostname)) {
-            snprintf(buf, sizeof(buf), "Unknown Host: %s\n", req->hostname);
-            error_html(buf);
-            return 1;
-        } else {
-            snprintf(buf, sizeof(buf), "%s\n", "Invalid Hostname");
-            error_html(buf);
-            return 1;
-        }
-    }
-
-    S.port(req->port);
-
-    S.getAddrInfo(AI);
-
-#if USE_IPV6
-    if ((s = socket( AI->ai_family, SOCK_STREAM, 0)) < 0) {
-#else
-    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
-#endif
-        int xerrno = errno;
-        snprintf(buf, sizeof(buf), "socket: %s\n", xstrerr(xerrno));
-        error_html(buf);
-        Ip::Address::FreeAddr(AI);
-        return 1;
-    }
-
-    if (connect(s, AI->ai_addr, AI->ai_addrlen) < 0) {
-        int xerrno = errno;
-        snprintf(buf, sizeof(buf), "connect %s: %s\n", S.toUrl(ipbuf,MAX_IPSTRLEN), xstrerr(xerrno));
-        error_html(buf);
-        Ip::Address::FreeAddr(AI);
-        close(s);
-        return 1;
-    }
-
-    Ip::Address::FreeAddr(AI);
-
-    // XXX: missing backward compatibility for old Squid.
-    // Squid-3.1 and older do not support http scheme manager requests.
-    // Squid-3.2 versions have bugs with https scheme manager requests.
-    l = snprintf(buf, sizeof(buf),
-                 "GET /squid-internal-mgr/%s%s%s HTTP/1.0\r\n" // HTTP/1.0 because this tool does not support Transfer-Encoding
-                 "Host: %s\r\n"
-                 "User-Agent: cachemgr.cgi/%s\r\n"
-                 "Accept: */*\r\n"
-                 "%s"           /* Authentication info or nothing */
-                 "\r\n",
-                 req->action,
-                 req->workers? "?workers=" : (req->processes ? "?processes=" : ""),
-                 req->workers? req->workers : (req->processes ? req->processes: ""),
-                 req->hostname,
-                 VERSION,
-                 make_auth_header(req));
-    if (write(s, buf, l) < 0) {
-        fprintf(stderr,"ERROR: (%d) writing request: '%s'\n", errno, buf);
-    } else {
-        debug("wrote request: '%s'\n", buf);
-    }
-    return read_reply(s, req);
-}
-
-int
-main(int argc, char *argv[])
-{
-    char *s;
-    cachemgr_request *req;
-
-    now = time(nullptr);
-#if _SQUID_WINDOWS_
-
-    Win32SockInit();
-    atexit(Win32SockCleanup);
-    _setmode( _fileno( stdin ), _O_BINARY );
-    _setmode( _fileno( stdout ), _O_BINARY );
-    _fmode = _O_BINARY;
-
-    if ((s = strrchr(argv[0], '\\')))
-#else
-
-    if ((s = strrchr(argv[0], '/')))
-#endif
-
-        progname = xstrdup(s + 1);
-    else
-        progname = xstrdup(argv[0]);
-
-    if ((s = getenv("SCRIPT_NAME")) != nullptr)
-        script_name = xstrdup(s);
-
-    char **args = argv;
-    while (argc > 1 && args[1][0] == '-') {
-        char option = args[1][1];
-        switch (option) {
-        case 'd':
-            debug_enabled = 1;
-            break;
-        default:
-            break;
-        }
-        ++args;
-        --argc;
-    }
-
-    req = read_request();
-
-    return process_request(req);
-}
-
-static char *
-read_post_request(void)
-{
-    char *s;
-
-    if ((s = getenv("REQUEST_METHOD")) == nullptr)
-        return nullptr;
-
-    if (0 != strcasecmp(s, "POST"))
-        return nullptr;
-
-    if ((s = getenv("CONTENT_LENGTH")) == nullptr)
-        return nullptr;
-
-    if (*s == '-') // negative length content huh?
-        return nullptr;
-
-    uint64_t len;
-
-    char *endptr = s+ strlen(s);
-    if ((len = strtoll(s, &endptr, 10)) <= 0)
-        return nullptr;
-
-    // limit the input to something reasonable.
-    // 4KB should be enough for the GET/POST data length, but may be extended.
-    size_t bufLen = (len < 4096 ? len : 4095);
-    char *buf = (char *)xmalloc(bufLen + 1);
-
-    size_t readLen = fread(buf, 1, bufLen, stdin);
-    if (readLen == 0) {
-        xfree(buf);
-        return nullptr;
-    }
-    buf[readLen] = '\0';
-    len -= readLen;
-
-    // purge the remainder of the request entity
-    while (len > 0 && readLen) {
-        char temp[65535];
-        readLen = fread(temp, 1, 65535, stdin);
-        len -= readLen;
-    }
-
-    return buf;
-}
-
-static char *
-read_get_request(void)
-{
-    char *s;
-
-    if ((s = getenv("QUERY_STRING")) == nullptr)
-        return nullptr;
-
-    return xstrdup(s);
-}
-
-static cachemgr_request *
-read_request(void)
-{
-    char *buf;
-
-    cachemgr_request *req;
-    char *s;
-    char *t = nullptr;
-    char *q;
-
-    if ((buf = read_post_request()) != nullptr)
-        (void) 0;
-    else if ((buf = read_get_request()) != nullptr)
-        (void) 0;
-    else
-        return nullptr;
-
-#if _SQUID_WINDOWS_
-
-    if (strlen(buf) == 0 || strlen(buf) == 4000)
-#else
-
-    if (strlen(buf) == 0)
-#endif
-    {
-        xfree(buf);
-        return nullptr;
-    }
-
-    req = (cachemgr_request *)xcalloc(1, sizeof(cachemgr_request));
-
-    for (s = strtok(buf, "&"); s != nullptr; s = strtok(nullptr, "&")) {
-        safe_free(t);
-        t = xstrdup(s);
-
-        if ((q = strchr(t, '=')) == nullptr)
-            continue;
-
-        *q = '\0';
-        ++q;
-
-        rfc1738_unescape(t);
-
-        rfc1738_unescape(q);
-
-        if (0 == strcmp(t, "server") && strlen(q))
-            req->server = xstrdup(q);
-        else if (0 == strcmp(t, "host") && strlen(q))
-            req->hostname = xstrdup(q);
-        else if (0 == strcmp(t, "port") && strlen(q))
-            req->port = atoi(q);
-        else if (0 == strcmp(t, "user_name") && strlen(q))
-            req->user_name = xstrdup(q);
-        else if (0 == strcmp(t, "passwd") && strlen(q))
-            req->passwd = xstrdup(q);
-        else if (0 == strcmp(t, "auth") && strlen(q))
-            req->pub_auth = xstrdup(q), decode_pub_auth(req);
-        else if (0 == strcmp(t, "operation"))
-            req->action = xstrdup(q);
-        else if (0 == strcmp(t, "workers") && strlen(q))
-            req->workers = xstrdup(q);
-        else if (0 == strcmp(t, "processes") && strlen(q))
-            req->processes = xstrdup(q);
-    }
-    safe_free(t);
-
-    if (req->server && !req->hostname) {
-        char *p;
-        req->hostname = strtok(req->server, ":");
-
-        if ((p = strtok(nullptr, ":")))
-            req->port = atoi(p);
-    }
-
-    make_pub_auth(req);
-    debug("cmgr: got req: host: '%s' port: %d uname: '%s' passwd: '%s' auth: '%s' oper: '%s' workers: '%s' processes: '%s'\n",
-          safe_str(req->hostname), req->port, safe_str(req->user_name), safe_str(req->passwd), safe_str(req->pub_auth), safe_str(req->action), safe_str(req->workers), safe_str(req->processes));
-    return req;
-}
-
-/* Routines to support authentication */
-
-/*
- * Encodes auth info into a "public" form.
- * Currently no powerful encryption is used.
- */
-static void
-make_pub_auth(cachemgr_request * req)
-{
-    static char buf[1024];
-    safe_free(req->pub_auth);
-    debug("cmgr: encoding for pub...\n");
-
-    if (!req->passwd || !strlen(req->passwd))
-        return;
-
-    auto *rfc1738_username = xstrdup(rfc1738_escape(safe_str(req->user_name)));
-    auto *rfc1738_passwd = xstrdup(rfc1738_escape(req->passwd));
-
-    /* host | time | user | passwd */
-    const int bufLen = snprintf(buf, sizeof(buf), "%s|%d|%s|%s",
-                                req->hostname,
-                                (int) now,
-                                rfc1738_username,
-                                rfc1738_passwd);
-    debug("cmgr: pre-encoded for pub: %s\n", buf);
-
-    safe_free(rfc1738_username);
-    safe_free(rfc1738_passwd);
-
-    const int encodedLen = base64_encode_len(bufLen);
-    req->pub_auth = (char *) xmalloc(encodedLen);
-    struct base64_encode_ctx ctx;
-    base64_encode_init(&ctx);
-    size_t blen = base64_encode_update(&ctx, req->pub_auth, bufLen, reinterpret_cast<uint8_t*>(buf));
-    blen += base64_encode_final(&ctx, req->pub_auth + blen);
-    req->pub_auth[blen] = '\0';
-    debug("cmgr: encoded: '%s'\n", req->pub_auth);
-}
-
-static void
-decode_pub_auth(cachemgr_request * req)
-{
-    const char *host_name;
-    const char *time_str;
-
-    debug("cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth));
-    safe_free(req->passwd);
-
-    if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname)))
-        return;
-
-    char *buf = static_cast<char*>(xmalloc(BASE64_DECODE_LENGTH(strlen(req->pub_auth))+1));
-    struct base64_decode_ctx ctx;
-    base64_decode_init(&ctx);
-    size_t decodedLen = 0;
-    if (!base64_decode_update(&ctx, &decodedLen, reinterpret_cast<uint8_t*>(buf), strlen(req->pub_auth), req->pub_auth) ||
-            !base64_decode_final(&ctx)) {
-        debug("cmgr: base64 decode failure. Incomplete auth token string.\n");
-        xfree(buf);
-        return;
-    }
-    buf[decodedLen] = '\0';
-
-    debug("cmgr: length ok\n");
-
-    /* parse ( a lot of memory leaks, but that is cachemgr style :) */
-    if ((host_name = strtok(buf, "|")) == nullptr) {
-        xfree(buf);
-        return;
-    }
-
-    debug("cmgr: decoded host: '%s'\n", host_name);
-
-    if ((time_str = strtok(nullptr, "|")) == nullptr) {
-        xfree(buf);
-        return;
-    }
-
-    debug("cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now);
-
-    char *user_name;
-    if ((user_name = strtok(nullptr, "|")) == nullptr) {
-        xfree(buf);
-        return;
-    }
-    rfc1738_unescape(user_name);
-
-    debug("cmgr: decoded uname: '%s'\n", user_name);
-
-    char *passwd;
-    if ((passwd = strtok(nullptr, "|")) == nullptr) {
-        xfree(buf);
-        return;
-    }
-    rfc1738_unescape(passwd);
-
-    debug("cmgr: decoded passwd: '%s'\n", passwd);
-
-    /* verify freshness and validity */
-    if (atoi(time_str) + passwd_ttl < now) {
-        xfree(buf);
-        return;
-    }
-
-    if (strcasecmp(host_name, req->hostname)) {
-        xfree(buf);
-        return;
-    }
-
-    debug("cmgr: verified auth. info.\n");
-
-    /* ok, accept */
-    safe_free(req->user_name);
-
-    req->user_name = xstrdup(user_name);
-
-    req->passwd = xstrdup(passwd);
-
-    xfree(buf);
-}
-
-static void
-reset_auth(cachemgr_request * req)
-{
-    safe_free(req->passwd);
-    safe_free(req->pub_auth);
-}
-
-static const char *
-make_auth_header(const cachemgr_request * req)
-{
-    static char buf[1024];
-    size_t stringLength = 0;
-
-    if (!req->passwd)
-        return "";
-
-    int bufLen = snprintf(buf, sizeof(buf), "%s:%s",
-                          req->user_name ? req->user_name : "",
-                          req->passwd);
-
-    int encodedLen = base64_encode_len(bufLen);
-    if (encodedLen <= 0)
-        return "";
-
-    char *str64 = static_cast<char *>(xmalloc(encodedLen));
-    struct base64_encode_ctx ctx;
-    base64_encode_init(&ctx);
-    size_t blen = base64_encode_update(&ctx, str64, bufLen, reinterpret_cast<uint8_t*>(buf));
-    blen += base64_encode_final(&ctx, str64+blen);
-    str64[blen] = '\0';
-
-    stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %.*s\r\n", (int)blen, str64);
-
-    assert(stringLength < sizeof(buf));
-
-    snprintf(&buf[stringLength], sizeof(buf) - stringLength, "Proxy-Authorization: Basic %.*s\r\n", (int)blen, str64);
-
-    xfree(str64);
-    return buf;
-}
-
-static int
-check_target_acl(const char *hostname, int port)
-{
-    char config_line[BUFSIZ];
-    FILE *fp = nullptr;
-    int ret = 0;
-    fp = fopen("cachemgr.conf", "r");
-
-    if (fp == nullptr)
-        fp = fopen(DEFAULT_CACHEMGR_CONFIG, "r");
-
-    if (fp == nullptr) {
-#ifdef CACHEMGR_HOSTNAME_DEFINED
-        // TODO: simplify and maybe get rid of CACHEMGR_HOSTNAME altogether
-        if (strcmp(hostname, CACHEMGR_HOSTNAME) == 0 && port == CACHE_HTTP_PORT)
-            return 1;
-
-#else
-
-        if (strcmp(hostname, "localhost") == 0)
-            return 1;
-
-        if (strcmp(hostname, getfullhostname()) == 0)
-            return 1;
-
-#endif
-
-        return 0;
-    }
-
-    while (fgets(config_line, BUFSIZ, fp)) {
-        char *token = nullptr;
-        strtok(config_line, " \r\n\t");
-
-        if (config_line[0] == '#')
-            continue;
-
-        if (config_line[0] == '\0')
-            continue;
-
-        if ((token = strtok(config_line, ":")) == nullptr)
-            continue;
-
-#if HAVE_FNMATCH_H
-
-        if (fnmatch(token, hostname, 0) != 0)
-            continue;
-
-#else
-
-        if (strcmp(token, hostname) != 0)
-            continue;
-
-#endif
-
-        if ((token = strtok(nullptr, ":")) != nullptr) {
-            int i;
-
-            if (strcmp(token, "*") == 0)
-
-                ;   /* Wildcard port specification */
-            else if (strcmp(token, "any") == 0)
-
-                ;   /* Wildcard port specification */
-            else if (sscanf(token, "%d", &i) != 1)
-                continue;
-
-            else if (i != port)
-                continue;
-        } else if (port != CACHE_HTTP_PORT)
-            continue;
-
-        ret = 1;
-
-        break;
-    }
-
-    fclose(fp);
-    return ret;
-}
-
diff --git a/tools/cachemgr.cgi.8.in b/tools/cachemgr.cgi.8.in
deleted file mode 100644 (file)
index ebc2b22..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-.if !'po4a'hide' .TH cachemgr.cgi 8
-.
-.SH NAME
-cachemgr.cgi \- Squid HTTP proxy manager CGI web interface
-.
-.SH SYNOPSIS
-.if !'po4a'hide' .B http://your.server/cgi-bin/cachemgr.cgi
-.
-.SH DESCRIPTION
-The cache manager (
-.B cachemgr.cgi
-) is a CGI utility for displaying statistics
-about the Squid HTTP proxy process as it runs. The cache manager is a
-convenient way to manage the cache and view statistics without logging
-into the server.
-.
-.SH CONFIGURATION
-Configuration examples for many common web servers can be found in the
-Squid FAQ wiki.
-.if !'po4a'hide' https://wiki.squid-cache.org/SquidFaq
-.PP
-.if !'po4a'hide' .I ./cachemgr.conf
-.br
-.if !'po4a'hide' .I @SYSCONFDIR@/cachemgr.conf
-.RS
-The access configuration file defining which Squid servers may
-be managed via this
-.B cachemgr.cgi
-program. Each line specifies a
-.BR server : port
-followed by an optional description
-.PP
-The server name may contain shell wildcard characters such as *, [] etc.
-A quick selection dropdown menu is automatically constructed from the simple
-server names.
-.PP
-Specifying :port is optional. If not specified then
-the default proxy port is assumed. :* or :any matches
-any port on the target server.
-.
-.SH SECURITY
-.B cachemgr.cgi
-calls the requested server on the requested port using HTTP
-and returns a formatted version of the response. To avoid abuse it is
-recommended to configure your web server to restrict access to the
-.B cachemgr.cgi
-program.
-.
-.SH AUTHOR
-Derived from Harvest. Further developed by numerous individuals from
-the internet community. Development is led by Duane Wessels of the
-National Laboratory for Applied Network Research and funded by
-the National Science Foundation.
-.
-.SH COPYRIGHT
-.PP
- * Copyright (C) 1996-2023 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.
-.
-.SH QUESTIONS
-Questions on the usage of this program can be sent to the
-.I Squid Users mailing list
-.if !'po4a'hide' <squid-users@lists.squid-cache.org>
-.
-.SH REPORTING BUGS
-See https://wiki.squid-cache.org/SquidFaq/BugReporting for details of what you need to include with your bug report.
-.PP
-Report bugs or bug fixes using https://bugs.squid-cache.org/
-.PP
-Report serious security bugs to
-.I Squid Bugs <squid-bugs@lists.squid-cache.org>
-.PP
-Report ideas for new improvements to the
-.I Squid Developers mailing list
-.if !'po4a'hide' <squid-dev@lists.squid-cache.org>
-.
-.SH SEE ALSO
-.if !'po4a'hide' .BR squid "(8), "
diff --git a/tools/cachemgr.conf b/tools/cachemgr.conf
deleted file mode 100644 (file)
index 4a69eb1..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-## Copyright (C) 1996-2023 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.
-##
-
-# This file controls which servers may be managed by
-# the cachemgr.cgi script
-#
-# The file consists of one server per line on the format
-#   hostname:port  description
-#
-# Specifying :port is optional. If not specified then
-# the default proxy port is assumed. :* or :any matches
-# any port on the target server.
-#
-# hostname is matched using shell filename matching, allowing
-# * and other shell wildcards.
-
-localhost