Search
j0ke.net Open Build Service
>
Projects
>
mozilla
>
MozillaFirefox
> system-proxies.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File system-proxies.patch of Package MozillaFirefox
Index: netwerk/base/public/nsISystemProxySettings.idl ================================================================================ --- allmakefiles.sh +++ allmakefiles.sh @@ -984,6 +984,7 @@ toolkit/components/downloads/src/Makefile toolkit/components/filepicker/Makefile toolkit/components/gnome/Makefile +toolkit/components/unixproxy/Makefile toolkit/components/help/Makefile toolkit/components/history/Makefile toolkit/components/history/public/Makefile --- browser/components/preferences/connection.xul +++ browser/components/preferences/connection.xul @@ -38,7 +38,12 @@ # # ***** END LICENSE BLOCK ***** -<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/connection.dtd"> +<!DOCTYPE prefwindow [ + <!ENTITY % connectionDTD SYSTEM "chrome://browser/locale/preferences/connection.dtd"> + %connectionDTD; + <!ENTITY % mainDTD SYSTEM "chrome://browser/locale/preferences/main.dtd"> + %mainDTD; +]> <?xml-stylesheet href="chrome://global/skin/"?> @@ -99,6 +104,7 @@ <radiogroup id="networkProxyType" preference="network.proxy.type" onsyncfrompreference="return gConnectionsDialog.readProxyType();"> <radio value="0" label="&directTypeRadio.label;" accesskey="&directTypeRadio.accesskey;"/> + <radio value="5" label="&systemDefaults.label;" /> <radio value="4" label="&WPADTypeRadio.label;" accesskey="&WPADTypeRadio.accesskey;"/> <radio value="1" label="&manualTypeRadio.label;" accesskey="&manualTypeRadio.accesskey;"/> <grid class="indent" flex="1"> --- browser/installer/unix/packages-static +++ browser/installer/unix/packages-static @@ -51,6 +51,7 @@ bin/xpicleanup ; [Components] +bin/components/libunixproxy.so bin/components/accessibility.xpt bin/components/accessibility-atk.xpt bin/components/appshell.xpt --- netwerk/base/public/Makefile.in +++ netwerk/base/public/Makefile.in @@ -98,6 +98,7 @@ nsIStreamTransportService.idl \ nsIStreamLoader.idl \ nsISyncStreamListener.idl \ + nsISystemProxySettings.idl \ nsIUnicharStreamLoader.idl \ nsIStandardURL.idl \ nsIURLParser.idl \ --- netwerk/base/public/nsISystemProxySettings.idl +++ netwerk/base/public/nsISystemProxySettings.idl @@ -0,0 +1,65 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Novell code. + * + * The Initial Developer of the Original Code is Novell. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert O'Callahan (rocallahan@novell.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" +#include "nsIURI.idl" + +%{C++ +#define NS_SYSTEMPROXYSETTINGS_CONTRACTID "@mozilla.org/system-proxy-settings;1" +%} + +/** + * This interface allows the proxy code to use platform-specific proxy + * settings when the proxy preference is set to "automatic discovery". If it can + * load a service with the above contract ID, it will use it to determine the + * PAC file name. If no PAC file is specified then the service itself will behave + * like a PAC file. + */ +[scriptable, uuid(a9f3ae38-b769-4e0b-9317-578388e326c9)] +interface nsISystemProxySettings : nsISupports +{ + /** + * If non-empty, use this PAC file. If empty, call getProxyForURI instead. + */ + readonly attribute AUTF8String PACURI; + + /** + * See nsIProxyAutoConfig::getProxyForURI; this function behaves exactly + * the same way. + */ + ACString getProxyForURI(in nsIURI aURI); +}; --- netwerk/base/src/nsPACMan.h +++ netwerk/base/src/nsPACMan.h @@ -128,6 +128,14 @@ */ PRBool IsLoading() { return mLoader != nsnull; } + /** + * Returns true if the given URI matches the URI of our PAC file. + */ + PRBool IsPACURI(nsIURI *uri) { + PRBool result; + return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result; + } + private: NS_DECL_NSISTREAMLOADEROBSERVER NS_DECL_NSIINTERFACEREQUESTOR @@ -163,14 +171,6 @@ void OnLoadFailure(); /** - * Returns true if the given URI matches the URI of our PAC file. - */ - PRBool IsPACURI(nsIURI *uri) { - PRBool result; - return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result; - } - - /** * Event fu for calling StartLoading asynchronously. */ PR_STATIC_CALLBACK(void *) LoadEvent_Handle(PLEvent *); --- netwerk/base/src/nsProtocolProxyService.cpp +++ netwerk/base/src/nsProtocolProxyService.cpp @@ -411,6 +411,12 @@ mProxyConfig = NS_STATIC_CAST(ProxyConfig, type); reloadPAC = PR_TRUE; } + + if (mProxyConfig == eProxyConfig_System) { + mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID); + } else { + mSystemProxySettings = nsnull; + } } if (!pref || !strcmp(pref, "network.proxy.http")) @@ -466,8 +472,10 @@ LoadHostFilters(tempString.get()); } - // We're done if not using PAC or WPAD - if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD) + // We're done if not using something that could give us a PAC URL + // (PAC, WPAD or System) + if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD && + mProxyConfig != eProxyConfig_System) return; // OK, we need to reload the PAC file if: @@ -482,17 +490,21 @@ if (mProxyConfig == eProxyConfig_PAC) { prefBranch->GetCharPref("network.proxy.autoconfig_url", getter_Copies(tempString)); - } - else if (mProxyConfig == eProxyConfig_WPAD) { + } else { // We diverge from the WPAD spec here in that we don't walk the // hosts's FQDN, stripping components until we hit a TLD. Doing so // is dangerous in the face of an incomplete list of TLDs, and TLDs // get added over time. We could consider doing only a single // substitution of the first component, if that proves to help // compatibility. - tempString.AssignLiteral("http://wpad/wpad.dat"); + if (mSystemProxySettings) + mSystemProxySettings->GetPACURI(tempString); + else + tempString.AssignLiteral("http://wpad/wpad.dat"); + } + if (!tempString.IsEmpty()) { + ConfigureFromPAC(tempString); } - ConfigureFromPAC(tempString); } } @@ -901,13 +913,16 @@ return NS_ERROR_OUT_OF_MEMORY; } - mFailedProxies.Clear(); - nsCOMPtr<nsIURI> pacURI; nsresult rv = NS_NewURI(getter_AddRefs(pacURI), spec); if (NS_FAILED(rv)) return rv; + if (mPACMan->IsPACURI(pacURI)) + return NS_OK; + + mFailedProxies.Clear(); + return mPACMan->LoadPACFromURI(pacURI); } @@ -917,8 +932,10 @@ nsresult aStatus, nsIProxyInfo **aResult) { - // We only support failover when a PAC file is configured. - if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD) + // We only support failover when a PAC file is configured, either + // directly or via system settings + if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD && + mProxyConfig != eProxyConfig_System) return NS_ERROR_NOT_AVAILABLE; // Verify that |aProxy| is one of our nsProxyInfo objects. @@ -1214,15 +1231,37 @@ if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY)) return NS_OK; // Can't proxy this (filters may not override) + if (mSystemProxySettings) { + nsCAutoString PACURI; + if (NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) && + !PACURI.IsEmpty()) { + // Switch to new PAC file if that setting has changed. If the setting + // hasn't changed, ConfigureFromPAC will exit early. + nsresult rv = ConfigureFromPAC(PACURI); + if (NS_FAILED(rv)) + return rv; + } else { + nsCAutoString proxy; + nsresult rv = mSystemProxySettings->GetProxyForURI(uri, proxy); + if (NS_SUCCEEDED(rv)) { + ProcessPACString(proxy, result); + return NS_OK; + } + // no proxy, stop search + return NS_OK; + } + } + // if proxies are enabled and this host:port combo is supposed to use a // proxy, check for a proxy. if (mProxyConfig == eProxyConfig_Direct || (mProxyConfig == eProxyConfig_Manual && !CanUseProxy(uri, info.defaultPort))) return NS_OK; - + // Proxy auto config magic... - if (mProxyConfig == eProxyConfig_PAC || mProxyConfig == eProxyConfig_WPAD) { + if (mProxyConfig == eProxyConfig_PAC || mProxyConfig == eProxyConfig_WPAD || + mProxyConfig == eProxyConfig_System) { // Do not query PAC now. *usePAC = PR_TRUE; return NS_OK; --- netwerk/base/src/nsProtocolProxyService.h +++ netwerk/base/src/nsProtocolProxyService.h @@ -48,6 +48,7 @@ #include "nsPIProtocolProxyService.h" #include "nsIProtocolProxyFilter.h" #include "nsIProxyAutoConfig.h" +#include "nsISystemProxySettings.h" #include "nsIProxyInfo.h" #include "nsIObserver.h" #include "nsDataHashtable.h" @@ -310,6 +311,7 @@ eProxyConfig_PAC, eProxyConfig_Direct4x, eProxyConfig_WPAD, + eProxyConfig_System, // use system proxy settings if available, otherwise WPAD eProxyConfig_Last }; @@ -371,6 +373,7 @@ PRBool mSOCKSProxyRemoteDNS; nsRefPtr<nsPACMan> mPACMan; // non-null if we are using PAC + nsCOMPtr<nsISystemProxySettings> mSystemProxySettings; PRTime mSessionStart; nsFailedProxyTable mFailedProxies; Index: Makefile.in =================================================================== RCS file: /cvsroot/mozilla/Makefile.in,v retrieving revision 1.299.2.18 diff -u -p -6 -r1.299.2.18 Makefile.in --- Makefile.in 14 Sep 2006 18:07:02 -0000 1.299.2.18 +++ Makefile.in 27 Nov 2006 19:04:14 -0000 @@ -282,12 +282,13 @@ tier_50_dirs += directory/xpcom endif ifndef MINIMO ifdef MOZ_XUL_APP ifdef MOZ_ENABLE_GTK2 tier_50_dirs += toolkit/components/gnome +tier_50_dirs += toolkit/components/unixproxy endif endif endif ifdef MOZ_LEAKY tier_50_dirs += tools/leaky --- toolkit/components/unixproxy/Makefile.in.orig 2006-11-27 21:25:50.000000000 +0100 +++ toolkit/components/unixproxy/Makefile.in 2006-11-27 21:26:18.000000000 +0100 @@ -0,0 +1,67 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is the Mozilla GNOME integration code. +# +# The Initial Developer of the Original Code is +# IBM Corporation. +# Portions created by the Initial Developer are Copyright (C) 2004 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Brian Ryner <bryner@brianryner.com> +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = unixproxy +MOZILLA_INTERNAL_API = 1 + +REQUIRES = \ + xpcom \ + string \ + necko \ + mozgnome \ + $(NULL) + +CPPSRCS = \ + nsUnixSystemProxySettings.cpp \ + $(NULL) + +LIBRARY_NAME = unixproxy +IS_COMPONENT = 1 +FORCE_SHARED_LIB = 1 + +EXTRA_DSO_LDOPTS += \ + $(MOZ_COMPONENT_LIBS) \ + $(NULL) + +include $(topsrcdir)/config/rules.mk Index: toolkit/components/gnome/nsGConfService.cpp =================================================================== RCS file: /cvsroot/mozilla/toolkit/components/gnome/Attic/nsGConfService.cpp,v retrieving revision 1.2 diff -u -p -6 -r1.2 nsGConfService.cpp --- toolkit/components/gnome/nsGConfService.cpp 15 Jul 2004 22:51:19 -0000 1.2 +++ toolkit/components/gnome/nsGConfService.cpp 29 May 2007 05:42:27 -0000 @@ -121,12 +121,70 @@ nsGConfService::GetFloat(const nsACStrin return NS_ERROR_FAILURE; } return NS_OK; } +class StringListEnumerator : public nsIUTF8StringEnumerator +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIUTF8STRINGENUMERATOR + + StringListEnumerator(GSList* aList) : mList(aList), mNext(aList) {} + virtual ~StringListEnumerator() { + g_slist_free(mList); + } + +private: + GSList* mList; + GSList* mNext; +}; + +NS_IMPL_ISUPPORTS1(StringListEnumerator, nsIUTF8StringEnumerator) + +NS_IMETHODIMP +StringListEnumerator::HasMore(PRBool* aResult) +{ + NS_PRECONDITION(aResult, "null ptr"); + *aResult = mNext != nsnull; + return NS_OK; +} + +NS_IMETHODIMP +StringListEnumerator::GetNext(nsACString& aResult) +{ + if (!mNext) + return NS_ERROR_UNEXPECTED; + aResult.Assign(NS_STATIC_CAST(char*, mNext->data)); + mNext = mNext->next; + return NS_OK; +} + +NS_IMETHODIMP +nsGConfService::GetStringList(const nsACString &aKey, + nsIUTF8StringEnumerator** aResult) +{ + GError* error = nsnull; + GSList* list = gconf_client_get_list(mClient, PromiseFlatCString(aKey).get(), + GCONF_VALUE_STRING, &error); + if (error) { + g_error_free(error); + return NS_ERROR_FAILURE; + } + + StringListEnumerator* enumerator = new StringListEnumerator(list); + if (!enumerator) { + g_slist_free(list); + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(*aResult = enumerator); + return NS_OK; +} + NS_IMETHODIMP nsGConfService::SetBool(const nsACString &aKey, PRBool aValue) { PRBool res = gconf_client_set_bool(mClient, PromiseFlatCString(aKey).get(), aValue, nsnull); Index: toolkit/components/gnome/nsIGConfService.idl =================================================================== RCS file: /cvsroot/mozilla/toolkit/components/gnome/Attic/nsIGConfService.idl,v retrieving revision 1.2 diff -u -p -6 -r1.2 nsIGConfService.idl --- toolkit/components/gnome/nsIGConfService.idl 15 Jul 2004 22:51:19 -0000 1.2 +++ toolkit/components/gnome/nsIGConfService.idl 29 May 2007 05:42:52 -0000 @@ -34,21 +34,23 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" +#include "nsIStringEnumerator.idl" [scriptable, uuid(01ac7b2e-c07c-465f-b35c-542eaef420a9)] interface nsIGConfService : nsISupports { /* Basic registry access */ boolean getBool(in AUTF8String key); AUTF8String getString(in AUTF8String key); long getInt(in AUTF8String key); float getFloat(in AUTF8String key); + nsIUTF8StringEnumerator getStringList(in AUTF8String key); void setBool(in AUTF8String key, in boolean value); void setString(in AUTF8String key, in AUTF8String value); void setInt(in AUTF8String key, in long value); void setFloat(in AUTF8String key, in float value); --- toolkit/components/unixproxy/nsUnixSystemProxySettings.cpp.orig 2007-05-29 07:45:58.000000000 +0200 +++ toolkit/components/unixproxy/nsUnixSystemProxySettings.cpp 2007-05-29 08:37:45.000000000 +0200 @@ -0,0 +1,422 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert O'Callahan (rocallahan@novell.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISystemProxySettings.h" +#include "nsIGenericFactory.h" +#include "nsIServiceManager.h" +#include "nsIGConfService.h" +#include "nsIURI.h" +#include "nsReadableUtils.h" +#include "nsArray.h" +#include "prnetdb.h" +#include "prenv.h" +#include "nsPrintfCString.h" +#include "nsNetUtil.h" + +class nsUnixSystemProxySettings : public nsISystemProxySettings { +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISYSTEMPROXYSETTINGS + + nsUnixSystemProxySettings() {} + nsresult Init(); + +private: + ~nsUnixSystemProxySettings() {} + + nsCOMPtr<nsIGConfService> mGConf; +}; + +NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings) + +nsresult +nsUnixSystemProxySettings::Init() +{ + // If this is a GNOME session, load gconf and try to use its preferences. + // If gconf is not available (which would be stupid) we'll proceed as if this + // was not a GNOME session, using *_PROXY environment variables. + const char* sessionType = PR_GetEnv("DESKTOP_SESSION"); + if (sessionType && !strcmp(sessionType, "gnome")) { + mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID); + } + return NS_OK; +} + +static PRBool +IsProxyMode(nsIGConfService* aGConf, const char* aMode) +{ + nsCAutoString mode; + return NS_SUCCEEDED(aGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/mode"), mode)) && + mode.EqualsASCII(aMode); +} + +nsresult +nsUnixSystemProxySettings::GetPACURI(nsACString& aResult) +{ + if (!mGConf || !IsProxyMode(mGConf, "auto")) + return NS_ERROR_FAILURE; + return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"), + aResult); +} + +static PRBool +IsInNoProxyList(const nsACString& aHost, PRInt32 aPort, const char* noProxyVal) +{ + NS_ASSERTION(aPort >= 0, "Negative port?"); + + nsCAutoString noProxy(noProxyVal); + if (noProxy.EqualsLiteral("*")) + return PR_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; + PRInt32 port = -1; + if (FindCharInReadable(':', colon, last)) { + ++colon; + nsDependentCSubstring portStr(colon, last); + nsCAutoString portStr2(portStr); + PRInt32 err; + port = portStr2.ToInteger(&err); + if (err != 0) { + 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); + if (StringEndsWith(aHost, hostStr, nsCaseInsensitiveCStringComparator())) + return PR_TRUE; + } + + pos = nextPos; + } + + return PR_FALSE; +} + +static void SetProxyResult(const char* aType, const nsACString& aHost, + PRInt32 aPort, nsACString& aResult) +{ + aResult.AppendASCII(aType); + aResult.Append(' '); + aResult.Append(aHost); + aResult.Append(':'); + aResult.Append(nsPrintfCString("%d", aPort)); +} + +static nsresult +GetProxyForURIFromEnvironment(const nsACString& aScheme, + const nsACString& aHost, + PRInt32 aPort, + nsACString& aResult) +{ + nsCAutoString envVar; + envVar.Append(aScheme); + envVar.AppendLiteral("_proxy"); + const char* proxyVal = PR_GetEnv(envVar.get()); + if (!proxyVal) { + proxyVal = PR_GetEnv("all_proxy"); + 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 = PR_GetEnv("no_proxy"); + if (noProxyVal && IsInNoProxyList(aHost, aPort, noProxyVal)) { + aResult.AppendLiteral("DIRECT"); + return NS_OK; + } + + // Use our URI parser to crack the proxy URI + nsCOMPtr<nsIURI> proxyURI; + nsresult rv = NS_NewURI(getter_AddRefs(proxyURI), proxyVal); + if (NS_FAILED(rv)) + return rv; + + // Is there a way to specify "socks://" or something in these environment + // variables? I can't find any documentation. + PRBool isHTTP; + rv = proxyURI->SchemeIs("http", &isHTTP); + if (NS_FAILED(rv)) + return rv; + if (!isHTTP) + return NS_ERROR_FAILURE; + + nsCAutoString proxyHost; + rv = proxyURI->GetHost(proxyHost); + if (NS_FAILED(rv)) + return rv; + PRInt32 proxyPort; + rv = proxyURI->GetPort(&proxyPort); + if (NS_FAILED(rv)) + return rv; + + SetProxyResult("PROXY", proxyHost, proxyPort, aResult); + return NS_OK; +} + +static nsresult +SetProxyResultFromGConf(nsIGConfService* aGConf, const char* aKeyBase, + const char* aType, nsACString& aResult) +{ + nsCAutoString hostKey; + hostKey.AppendASCII(aKeyBase); + hostKey.AppendLiteral("host"); + nsCAutoString host; + nsresult rv = aGConf->GetString(hostKey, host); + if (NS_FAILED(rv)) + return rv; + if (host.IsEmpty()) + return NS_ERROR_FAILURE; + + nsCAutoString portKey; + portKey.AppendASCII(aKeyBase); + portKey.AppendLiteral("port"); + PRInt32 port; + rv = aGConf->GetInt(portKey, &port); + if (NS_FAILED(rv)) + return rv; + + SetProxyResult(aType, host, port, aResult); + return NS_OK; +} + +/* copied from nsProtocolProxyService.cpp --- we should share this! */ +static void +proxy_MaskIPv6Addr(PRIPv6Addr &addr, PRUint16 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 PRBool ConvertToIPV6Addr(const nsACString& aName, + PRIPv6Addr* aAddr) +{ + PRNetAddr addr; + if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS) + return PR_FALSE; + + PRIPv6Addr ipv6; + // convert parsed address to IPv6 + if (addr.raw.family == PR_AF_INET) { + // convert to IPv4-mapped address + PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &ipv6); + } else if (addr.raw.family == PR_AF_INET6) { + // copy the address + memcpy(&ipv6, &addr.ipv6.ip, sizeof(PRIPv6Addr)); + } else { + return PR_FALSE; + } + + return PR_TRUE; +} + +static PRBool GConfIgnoreHost(const nsACString& aIgnore, + const nsACString& aHost) +{ + if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator())) + return PR_TRUE; + + if (StringBeginsWith(aIgnore, NS_LITERAL_CSTRING("*")) && + StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1), + nsCaseInsensitiveCStringComparator())) + return PR_TRUE; + + PRInt32 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); + nsCAutoString maskStr2(maskStr); + PRInt32 err; + mask = maskStr2.ToInteger(&err); + if (err != 0) { + mask = 128; + } + --slash; + } else { + slash = end; + } + + PRIPv6Addr ignoreAddr, hostAddr; + if (!ConvertToIPV6Addr(aIgnore, &ignoreAddr) || + !ConvertToIPV6Addr(aHost, &hostAddr)) + return PR_FALSE; + + proxy_MaskIPv6Addr(ignoreAddr, mask); + proxy_MaskIPv6Addr(hostAddr, mask); + + return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0; +} + +static nsresult +GetProxyForURIFromGConf(nsIGConfService* aGConf, + const nsACString& aScheme, + const nsACString& aHost, + PRInt32 aPort, + nsACString& aResult) +{ + if (!IsProxyMode(aGConf, "manual")) { + aResult.AppendLiteral("DIRECT"); + return NS_OK; + } + + nsCOMPtr<nsIUTF8StringEnumerator> ignoreList; + if (NS_SUCCEEDED(aGConf->GetStringList(NS_LITERAL_CSTRING("/system/http_proxy/ignore_hosts"), + getter_AddRefs(ignoreList))) && ignoreList) { + while (PR_TRUE) { + PRBool hasMore; + if (NS_FAILED(ignoreList->HasMore(&hasMore)) || !hasMore) + break; + nsCAutoString s; + if (NS_SUCCEEDED(ignoreList->GetNext(s))) { + if (GConfIgnoreHost(s, aHost)) { + aResult.AppendLiteral("DIRECT"); + return NS_OK; + } + } + } + } + + nsresult rv = SetProxyResultFromGConf(aGConf, "/system/proxy/socks_", "SOCKS", aResult); + if (NS_SUCCEEDED(rv)) + return rv; + + if (aScheme.LowerCaseEqualsLiteral("http")) { + rv = SetProxyResultFromGConf(aGConf, "/system/http_proxy/", "PROXY", aResult); + } else if (aScheme.LowerCaseEqualsLiteral("https")) { + rv = SetProxyResultFromGConf(aGConf, "/system/proxy/secure_", "PROXY", aResult); + } else if (aScheme.LowerCaseEqualsLiteral("ftp")) { + rv = SetProxyResultFromGConf(aGConf, "/system/proxy/ftp_", "PROXY", aResult); + } else { + rv = NS_ERROR_FAILURE; + } + + if (NS_FAILED(rv)) { + aResult.AppendLiteral("DIRECT"); + } + return NS_OK; +} + +nsresult +nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult) +{ + nsCAutoString scheme; + nsresult rv = aURI->GetScheme(scheme); + if (NS_FAILED(rv)) + return rv; + + nsCAutoString host; + rv = aURI->GetHost(host); + if (NS_FAILED(rv)) + return rv; + + PRInt32 port; + rv = aURI->GetPort(&port); + if (NS_FAILED(rv)) + return rv; + + if (!mGConf) + return GetProxyForURIFromEnvironment(scheme, host, port, aResult); + + return GetProxyForURIFromGConf(mGConf, scheme, host, port, aResult); +} + +#define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\ + { 0x0fa3158c, 0xd5a7, 0x43de, \ + {0x91, 0x81, 0xa2, 0x85, 0xe7, 0x4c, 0xf1, 0xd4 } } + +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUnixSystemProxySettings, Init) + +static const nsModuleComponentInfo components[] = { + { "Unix System Proxy Settings Service", + NS_UNIXSYSTEMPROXYSERVICE_CID, + NS_SYSTEMPROXYSETTINGS_CONTRACTID, + nsUnixSystemProxySettingsConstructor } +}; + +NS_IMPL_NSGETMODULE(unixproxy, components)