summaryrefslogtreecommitdiffstats
path: root/apt-pkg/contrib/proxy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib/proxy.cc')
-rw-r--r--apt-pkg/contrib/proxy.cc99
1 files changed, 99 insertions, 0 deletions
diff --git a/apt-pkg/contrib/proxy.cc b/apt-pkg/contrib/proxy.cc
new file mode 100644
index 0000000..a99f44f
--- /dev/null
+++ b/apt-pkg/contrib/proxy.cc
@@ -0,0 +1,99 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+/* ######################################################################
+
+ Proxy - Proxy related functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include <config.h>
+
+#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;
+}
+ /*}}}*/