Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/toolkit/system/unixproxy/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 12 kB image not shown  

Quelle  nsUnixSystemProxySettings.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "nsISystemProxySettings.h"
#include "mozilla/Components.h"
#include "nsIURI.h"
#include "nsArrayUtils.h"
#include "prnetdb.h"
#include "prenv.h"
#include "nsInterfaceHashtable.h"
#include "nsHashtablesFwd.h"
#include "nsHashKeys.h"
#include "nsNetUtil.h"
#include "nsISupportsPrimitives.h"
#include "nsIGSettingsService.h"
#include "nsReadableUtils.h"

using namespace mozilla;

class nsUnixSystemProxySettings final : public nsISystemProxySettings {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSISYSTEMPROXYSETTINGS

  nsUnixSystemProxySettings() : mSchemeProxySettings(4) {}
  void Init();

 private:
  ~nsUnixSystemProxySettings() = default;

  nsCOMPtr<nsIGSettingsService> mGSettings;
  nsCOMPtr<nsIGSettingsCollection> mProxySettings;
  nsInterfaceHashtable<nsCStringHashKey, nsIGSettingsCollection>
      mSchemeProxySettings;
  nsresult GetProxyFromGSettings(const nsACString& aScheme,
                                 const nsACString& aHost, int32_t aPort,
                                 nsACString& aResult);
  nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType,
                                       nsACString& aResult);
};

NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings)

NS_IMETHODIMP
nsUnixSystemProxySettings::GetMainThreadOnly(bool* aMainThreadOnly) {
  // dbus prevents us from being threadsafe, but this routine should not block
  // anyhow
  *aMainThreadOnly = true;
  return NS_OK;
}

void nsUnixSystemProxySettings::Init() {
  mGSettings = do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
  if (mGSettings) {
    mGSettings->GetCollectionForSchema("org.gnome.system.proxy"_ns,
                                       getter_AddRefs(mProxySettings));
  }
}

nsresult nsUnixSystemProxySettings::GetPACURI(nsACString& aResult) {
  if (mProxySettings) {
    nsCString proxyMode;
    // Check if mode is auto
    nsresult rv = mProxySettings->GetString("mode"_ns, proxyMode);
    if (rv == NS_OK && proxyMode.EqualsLiteral("auto")) {
      return mProxySettings->GetString("autoconfig-url"_ns, aResult);
    }
  }

  // Return an empty string when auto mode is not set.
  aResult.Truncate();
  return NS_OK;
}

static bool IsInNoProxyList(const nsACString& aHost, int32_t aPort,
                            const char* noProxyVal) {
  NS_ASSERTION(aPort >= 0, "Negative port?");

  nsAutoCString noProxy(noProxyVal);
  if (noProxy.EqualsLiteral("*")) return true;

  noProxy.StripWhitespace();

  nsReadingIterator<char> pos;
  nsReadingIterator<char> end;
  noProxy.BeginReading(pos);
  noProxy.EndReading(end);
  while (pos != end) {
    nsReadingIterator<char> last = pos;
    nsReadingIterator<char> nextPos;
    if (FindCharInReadable(',', last, end)) {
      nextPos = last;
      ++nextPos;
    } else {
      last = end;
      nextPos = end;
    }

    nsReadingIterator<char> colon = pos;
    int32_t port = -1;
    if (FindCharInReadable(':', colon, last)) {
      ++colon;
      nsDependentCSubstring portStr(colon, last);
      nsAutoCString portStr2(
          portStr);  // We need this for ToInteger. String API's suck.
      nsresult err;
      port = portStr2.ToInteger(&err);
      if (NS_FAILED(err)) {
        port = -2;  // don't match any port, so we ignore this pattern
      }
      --colon;
    } else {
      colon = last;
    }

    if (port == -1 || port == aPort) {
      nsDependentCSubstring hostStr(pos, colon);
      // By using StringEndsWith instead of an equality comparator, we can
      // include sub-domains
      if (StringEndsWith(aHost, hostStr, nsCaseInsensitiveCStringComparator))
        return true;
    }

    pos = nextPos;
  }

  return false;
}

static void SetProxyResult(const char* aType, const nsACString& aHost,
                           int32_t aPort, nsACString& aResult) {
  aResult.AssignASCII(aType);
  aResult.Append(' ');
  aResult.Append(aHost);
  if (aPort > 0) {
    aResult.Append(':');
    aResult.AppendInt(aPort);
  }
}

static void SetProxyResultDirect(nsACString& aResult) {
  aResult.AssignLiteral("DIRECT");
}

static const char* GetEnvRetryUppercase(const nsCString& aEnv) {
  nsAutoCString env(aEnv);
  const char* proxyVal = PR_GetEnv(env.get());
  if (proxyVal) {
    return proxyVal;
  }
  ToUpperCase(env);
  proxyVal = PR_GetEnv(env.get());
  return proxyVal;
}

static nsresult GetProxyFromEnvironment(const nsACString& aScheme,
                                        const nsACString& aHost, int32_t aPort,
                                        nsACString& aResult) {
  nsAutoCString envVar;
  envVar.Append(aScheme);
  envVar.AppendLiteral("_proxy");
  const char* proxyVal = GetEnvRetryUppercase(envVar);
  if (!proxyVal && aScheme == "ws") {
    proxyVal = GetEnvRetryUppercase("http_proxy"_ns);
  } else if (!proxyVal && aScheme == "wss") {
    proxyVal = GetEnvRetryUppercase("https_proxy"_ns);
  }
  if (!proxyVal) {
    proxyVal = GetEnvRetryUppercase("all_proxy"_ns);
    if (!proxyVal) {
      // Return failure so that the caller can detect the failure and
      // fall back to other proxy detection (e.g., WPAD)
      return NS_ERROR_FAILURE;
    }
  }

  const char* noProxyVal = GetEnvRetryUppercase("no_proxy"_ns);
  if (noProxyVal && IsInNoProxyList(aHost, aPort, noProxyVal)) {
    SetProxyResultDirect(aResult);
    return NS_OK;
  }

  // Use our URI parser to crack the proxy URI
  nsCOMPtr<nsIURI> proxyURI;
  nsresult rv = NS_NewURI(getter_AddRefs(proxyURI), proxyVal);
  NS_ENSURE_SUCCESS(rv, rv);

  // Is there a way to specify "socks://" or something in these environment
  // variables? I can't find any documentation.
  if (!proxyURI->SchemeIs("http")) {
    return NS_ERROR_UNKNOWN_PROTOCOL;
  }

  nsAutoCString proxyHost;
  rv = proxyURI->GetHost(proxyHost);
  NS_ENSURE_SUCCESS(rv, rv);

  int32_t proxyPort;
  rv = proxyURI->GetPort(&proxyPort);
  NS_ENSURE_SUCCESS(rv, rv);

  SetProxyResult("PROXY", proxyHost, proxyPort, aResult);
  return NS_OK;
}

nsresult nsUnixSystemProxySettings::SetProxyResultFromGSettings(
    const char* aKeyBase, const char* aType, nsACString& aResult) {
  nsDependentCString key(aKeyBase);

  nsCOMPtr<nsIGSettingsCollection> proxy_settings =
      mSchemeProxySettings.Get(key);
  nsresult rv;
  if (!proxy_settings) {
    rv =
        mGSettings->GetCollectionForSchema(key, getter_AddRefs(proxy_settings));
    NS_ENSURE_SUCCESS(rv, rv);

    mSchemeProxySettings.InsertOrUpdate(key, proxy_settings);
  }

  nsAutoCString host;
  rv = proxy_settings->GetString("host"_ns, host);
  NS_ENSURE_SUCCESS(rv, rv);
  if (host.IsEmpty()) return NS_ERROR_FAILURE;

  int32_t port;
  rv = proxy_settings->GetInt("port"_ns, &port);
  NS_ENSURE_SUCCESS(rv, rv);

  /* When port is 0, proxy is not considered as enabled even if host is set. */
  if (port == 0) return NS_ERROR_FAILURE;

  SetProxyResult(aType, host, port, aResult);
  return NS_OK;
}

/* copied from nsProtocolProxyService.cpp --- we should share this! */
static void proxy_MaskIPv6Addr(PRIPv6Addr& addr, uint16_t mask_len) {
  if (mask_len == 128) return;

  if (mask_len > 96) {
    addr.pr_s6_addr32[3] =
        PR_htonl(PR_ntohl(addr.pr_s6_addr32[3]) & (~0L << (128 - mask_len)));
  } else if (mask_len > 64) {
    addr.pr_s6_addr32[3] = 0;
    addr.pr_s6_addr32[2] =
        PR_htonl(PR_ntohl(addr.pr_s6_addr32[2]) & (~0L << (96 - mask_len)));
  } else if (mask_len > 32) {
    addr.pr_s6_addr32[3] = 0;
    addr.pr_s6_addr32[2] = 0;
    addr.pr_s6_addr32[1] =
        PR_htonl(PR_ntohl(addr.pr_s6_addr32[1]) & (~0L << (64 - mask_len)));
  } else {
    addr.pr_s6_addr32[3] = 0;
    addr.pr_s6_addr32[2] = 0;
    addr.pr_s6_addr32[1] = 0;
    addr.pr_s6_addr32[0] =
        PR_htonl(PR_ntohl(addr.pr_s6_addr32[0]) & (~0L << (32 - mask_len)));
  }
}

static bool ConvertToIPV6Addr(const nsACString& aName, PRIPv6Addr* aAddr,
                              int32_t* aMask) {
  PRNetAddr addr;
  // try to convert hostname to IP
  if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS)
    return false;

  // convert parsed address to IPv6
  if (addr.raw.family == PR_AF_INET) {
    // convert to IPv4-mapped address
    PR_ConvertIPv4AddrToIPv6(addr.inet.ip, aAddr);
    if (aMask) {
      if (*aMask <= 32)
        *aMask += 96;
      else
        return false;
    }
  } else if (addr.raw.family == PR_AF_INET6) {
    // copy the address
    memcpy(aAddr, &addr.ipv6.ip, sizeof(PRIPv6Addr));
  } else {
    return false;
  }

  return true;
}

static bool HostIgnoredByProxy(const nsACString& aIgnore,
                               const nsACString& aHost) {
  if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator)) return true;

  if (aIgnore.First() == '*' &&
      StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1),
                     nsCaseInsensitiveCStringComparator))
    return true;

  int32_t mask = 128;
  nsReadingIterator<char> start;
  nsReadingIterator<char> slash;
  nsReadingIterator<char> end;
  aIgnore.BeginReading(start);
  aIgnore.BeginReading(slash);
  aIgnore.EndReading(end);
  if (FindCharInReadable('/', slash, end)) {
    ++slash;
    nsDependentCSubstring maskStr(slash, end);
    nsAutoCString maskStr2(maskStr);
    nsresult err;
    mask = maskStr2.ToInteger(&err);
    if (NS_FAILED(err)) {
      mask = 128;
    }
    --slash;
  } else {
    slash = end;
  }

  nsDependentCSubstring ignoreStripped(start, slash);
  PRIPv6Addr ignoreAddr, hostAddr;
  if (!ConvertToIPV6Addr(ignoreStripped, &ignoreAddr, &mask) ||
      !ConvertToIPV6Addr(aHost, &hostAddr, nullptr))
    return false;

  proxy_MaskIPv6Addr(ignoreAddr, mask);
  proxy_MaskIPv6Addr(hostAddr, mask);

  return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0;
}

nsresult nsUnixSystemProxySettings::GetProxyFromGSettings(
    const nsACString& aScheme, const nsACString& aHost, int32_t aPort,
    nsACString& aResult) {
  nsCString proxyMode;
  nsresult rv = mProxySettings->GetString("mode"_ns, proxyMode);
  NS_ENSURE_SUCCESS(rv, rv);

  // return NS_ERROR_FAILURE when no proxy is set
  if (!proxyMode.EqualsLiteral("manual")) {
    return NS_ERROR_FAILURE;
  }

  nsCOMPtr<nsIArray> ignoreList;
  if (NS_SUCCEEDED(mProxySettings->GetStringList("ignore-hosts"_ns,
                                                 getter_AddRefs(ignoreList))) &&
      ignoreList) {
    uint32_t len = 0;
    ignoreList->GetLength(&len);
    for (uint32_t i = 0; i < len; ++i) {
      nsCOMPtr<nsISupportsCString> str = do_QueryElementAt(ignoreList, i);
      if (str) {
        nsCString s;
        if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) {
          if (HostIgnoredByProxy(s, aHost)) {
            SetProxyResultDirect(aResult);
            return NS_OK;
          }
        }
      }
    }
  }

  if (aScheme.LowerCaseEqualsLiteral("http")) {
    rv = SetProxyResultFromGSettings("org.gnome.system.proxy.http""PROXY",
                                     aResult);
  } else if (aScheme.LowerCaseEqualsLiteral("https")) {
    rv = SetProxyResultFromGSettings("org.gnome.system.proxy.https""PROXY",
                                     aResult);
    /* Try to use HTTP proxy when HTTPS proxy is not explicitly defined */
    if (rv != NS_OK)
      rv = SetProxyResultFromGSettings("org.gnome.system.proxy.http""PROXY",
                                       aResult);
  } else {
    rv = NS_ERROR_FAILURE;
  }
  if (rv != NS_OK) {
    /* If proxy for scheme is not specified, use SOCKS proxy for all schemes */
    rv = SetProxyResultFromGSettings("org.gnome.system.proxy.socks""SOCKS",
                                     aResult);
  }

  if (NS_FAILED(rv)) {
    SetProxyResultDirect(aResult);
  }

  return NS_OK;
}

nsresult nsUnixSystemProxySettings::GetProxyForURI(const nsACString& aSpec,
                                                   const nsACString& aScheme,
                                                   const nsACString& aHost,
                                                   const int32_t aPort,
                                                   nsACString& aResult) {
  if (mProxySettings) {
    nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult);
    if (NS_SUCCEEDED(rv)) return rv;
  }

  return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult);
}

NS_IMETHODIMP
nsUnixSystemProxySettings::GetSystemWPADSetting(bool* aSystemWPADSetting) {
  *aSystemWPADSetting = false;
  return NS_OK;
}

NS_IMPL_COMPONENT_FACTORY(nsUnixSystemProxySettings) {
  auto result = MakeRefPtr<nsUnixSystemProxySettings>();
  result->Init();
  return result.forget().downcast<nsISupports>();
}

Messung V0.5
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.