diff options
Diffstat (limited to '')
-rw-r--r-- | apt-pkg/contrib/proxy.cc | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/apt-pkg/contrib/proxy.cc b/apt-pkg/contrib/proxy.cc new file mode 100644 index 0000000..6dc3b06 --- /dev/null +++ b/apt-pkg/contrib/proxy.cc @@ -0,0 +1,97 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Proxy - Proxy related functions + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <apt-pkg/configuration.h> +#include <apt-pkg/error.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/strutl.h> + +#include <algorithm> +#include <iostream> +#include <fcntl.h> +#include <unistd.h> + +#include "proxy.h" + /*}}}*/ + +// AutoDetectProxy - auto detect proxy /*{{{*/ +// --------------------------------------------------------------------- +/* */ +static std::vector<std::string> CompatibleProxies(URI const &URL) +{ + if (URL.Access == "http" || URL.Access == "https") + return {"http", "https", "socks5h"}; + return {URL.Access}; +} + +bool AutoDetectProxy(URI &URL) +{ + // we support both http/https debug options + bool Debug = _config->FindB("Debug::Acquire::"+URL.Access,false); + + // the user already explicitly set a proxy for this host + if(_config->Find("Acquire::"+URL.Access+"::proxy::"+URL.Host, "") != "") + return true; + + // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old + // name without the dash ("-") + std::string AutoDetectProxyCmd = _config->Find("Acquire::"+URL.Access+"::Proxy-Auto-Detect", + _config->Find("Acquire::"+URL.Access+"::ProxyAutoDetect")); + + if (AutoDetectProxyCmd.empty()) + return true; + + if (Debug) + std::clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << std::endl; + + if (faccessat(AT_FDCWD, AutoDetectProxyCmd.c_str(), R_OK | X_OK, AT_EACCESS) != 0) + return _error->Errno("access", "ProxyAutoDetect command '%s' can not be executed!", AutoDetectProxyCmd.c_str()); + + std::string const urlstring = URL; + std::vector<const char *> Args; + Args.push_back(AutoDetectProxyCmd.c_str()); + Args.push_back(urlstring.c_str()); + Args.push_back(nullptr); + FileFd PipeFd; + pid_t Child; + if (Popen(&Args[0], PipeFd, Child, FileFd::ReadOnly, false, true) == false) + return _error->Error("ProxyAutoDetect command '%s' failed!", AutoDetectProxyCmd.c_str()); + char buf[512]; + bool const goodread = PipeFd.ReadLine(buf, sizeof(buf)) != nullptr; + PipeFd.Close(); + if (ExecWait(Child, "ProxyAutoDetect") == false) + return false; + // no output means the detector has no idea which proxy to use + // and apt will use the generic proxy settings + if (goodread == false) + return true; + auto const cleanedbuf = _strstrip(buf); + // We warn about this as the implementor probably meant to use DIRECT instead + if (cleanedbuf[0] == '\0') + { + _error->Warning("ProxyAutoDetect command returned an empty line"); + return true; + } + + if (Debug) + std::clog << "auto detect command returned: '" << cleanedbuf << "'" << std::endl; + + auto compatibleTypes = CompatibleProxies(URL); + bool compatible = strcmp(cleanedbuf, "DIRECT") == 0 || + compatibleTypes.end() != std::find_if(compatibleTypes.begin(), + compatibleTypes.end(), [cleanedbuf](std::string &compat) { + return strstr(cleanedbuf, compat.c_str()) == cleanedbuf; + }); + + if (compatible) + _config->Set("Acquire::"+URL.Access+"::proxy::"+URL.Host, cleanedbuf); + + return true; +} + /*}}}*/ |