Logoj0ke.net Open Build Service > Projects > mozilla > mozilla-xulrunner181 > system-proxies.patch
Sign Up | Log In

File system-proxies.patch of Package mozilla-xulrunner181 (Revision e78671003c7f81a36f7a42da57b84858)

Currently displaying revision e78671003c7f81a36f7a42da57b84858, show latest

x
 
1
Index: netwerk/base/public/nsISystemProxySettings.idl
2
================================================================================
3
--- allmakefiles.sh
4
+++ allmakefiles.sh
5
@@ -984,6 +984,7 @@
6
 toolkit/components/downloads/src/Makefile
7
 toolkit/components/filepicker/Makefile
8
 toolkit/components/gnome/Makefile
9
+toolkit/components/unixproxy/Makefile
10
 toolkit/components/help/Makefile
11
 toolkit/components/history/Makefile
12
 toolkit/components/history/public/Makefile
13
--- netwerk/base/public/Makefile.in
14
+++ netwerk/base/public/Makefile.in
15
@@ -98,6 +98,7 @@
16
        nsIStreamTransportService.idl \
17
        nsIStreamLoader.idl \
18
        nsISyncStreamListener.idl \
19
+       nsISystemProxySettings.idl \
20
        nsIUnicharStreamLoader.idl \
21
        nsIStandardURL.idl \
22
        nsIURLParser.idl \
23
--- netwerk/base/public/nsISystemProxySettings.idl
24
+++ netwerk/base/public/nsISystemProxySettings.idl
25
@@ -0,0 +1,65 @@
26
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
27
+/* ***** BEGIN LICENSE BLOCK *****
28
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
29
+ *
30
+ * The contents of this file are subject to the Mozilla Public License Version
31
+ * 1.1 (the "License"); you may not use this file except in compliance with
32
+ * the License. You may obtain a copy of the License at
33
+ * http://www.mozilla.org/MPL/
34
+ *
35
+ * Software distributed under the License is distributed on an "AS IS" basis,
36
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
37
+ * for the specific language governing rights and limitations under the
38
+ * License.
39
+ *
40
+ * The Original Code is Novell code.
41
+ *
42
+ * The Initial Developer of the Original Code is Novell.
43
+ * Portions created by the Initial Developer are Copyright (C) 2005
44
+ * the Initial Developer. All Rights Reserved.
45
+ *
46
+ * Contributor(s):
47
+ *    Robert O'Callahan (rocallahan@novell.com)
48
+ *
49
+ * Alternatively, the contents of this file may be used under the terms of
50
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
51
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
52
+ * in which case the provisions of the GPL or the LGPL are applicable instead
53
+ * of those above. If you wish to allow use of your version of this file only
54
+ * under the terms of either the GPL or the LGPL, and not to allow others to
55
+ * use your version of this file under the terms of the MPL, indicate your
56
+ * decision by deleting the provisions above and replace them with the notice
57
+ * and other provisions required by the GPL or the LGPL. If you do not delete
58
+ * the provisions above, a recipient may use your version of this file under
59
+ * the terms of any one of the MPL, the GPL or the LGPL.
60
+ *
61
+ * ***** END LICENSE BLOCK ***** */
62
+
63
+#include "nsISupports.idl"
64
+#include "nsIURI.idl"
65
+
66
+%{C++
67
+#define NS_SYSTEMPROXYSETTINGS_CONTRACTID "@mozilla.org/system-proxy-settings;1"
68
+%}
69
+
70
+/** 
71
+ * This interface allows the proxy code to use platform-specific proxy
72
+ * settings when the proxy preference is set to "automatic discovery". If it can
73
+ * load a service with the above contract ID, it will use it to determine the
74
+ * PAC file name. If no PAC file is specified then the service itself will behave
75
+ * like a PAC file.
76
+ */
77
+[scriptable, uuid(a9f3ae38-b769-4e0b-9317-578388e326c9)]
78
+interface nsISystemProxySettings : nsISupports
79
+{
80
+    /**
81
+     * If non-empty, use this PAC file. If empty, call getProxyForURI instead.
82
+     */
83
+    readonly attribute AUTF8String PACURI;
84
+    
85
+    /**
86
+     * See nsIProxyAutoConfig::getProxyForURI; this function behaves exactly
87
+     * the same way.
88
+     */
89
+    ACString getProxyForURI(in nsIURI aURI);
90
+};
91
--- netwerk/base/src/nsPACMan.h
92
+++ netwerk/base/src/nsPACMan.h
93
@@ -128,6 +128,14 @@
94
    */
95
   PRBool IsLoading() { return mLoader != nsnull; }
96
 
97
+  /**
98
+   * Returns true if the given URI matches the URI of our PAC file.
99
+   */
100
+  PRBool IsPACURI(nsIURI *uri) {
101
+    PRBool result;
102
+    return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result;
103
+  }
104
+
105
 private:
106
   NS_DECL_NSISTREAMLOADEROBSERVER
107
   NS_DECL_NSIINTERFACEREQUESTOR
108
@@ -163,14 +171,6 @@
109
   void OnLoadFailure();
110
 
111
   /**
112
-   * Returns true if the given URI matches the URI of our PAC file.
113
-   */
114
-  PRBool IsPACURI(nsIURI *uri) {
115
-    PRBool result;
116
-    return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result;
117
-  }
118
-
119
-  /**
120
    * Event fu for calling StartLoading asynchronously.
121
    */
122
   PR_STATIC_CALLBACK(void *) LoadEvent_Handle(PLEvent *);
123
--- netwerk/base/src/nsProtocolProxyService.cpp
124
+++ netwerk/base/src/nsProtocolProxyService.cpp
125
@@ -411,6 +411,12 @@
126
             mProxyConfig = NS_STATIC_CAST(ProxyConfig, type);
127
             reloadPAC = PR_TRUE;
128
         }
129
+
130
+        if (mProxyConfig == eProxyConfig_System) {
131
+            mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
132
+        } else {
133
+            mSystemProxySettings = nsnull;
134
+        }
135
     }
136
 
137
     if (!pref || !strcmp(pref, "network.proxy.http"))
138
@@ -466,8 +472,10 @@
139
             LoadHostFilters(tempString.get());
140
     }
141
 
142
-    // We're done if not using PAC or WPAD
143
-    if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD)
144
+    // We're done if not using something that could give us a PAC URL
145
+    // (PAC, WPAD or System)
146
+    if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD &&
147
+        mProxyConfig != eProxyConfig_System)
148
         return;
149
 
150
     // OK, we need to reload the PAC file if:
151
@@ -482,17 +490,21 @@
152
         if (mProxyConfig == eProxyConfig_PAC) {
153
             prefBranch->GetCharPref("network.proxy.autoconfig_url",
154
                                     getter_Copies(tempString));
155
-        }
156
-        else if (mProxyConfig == eProxyConfig_WPAD) {
157
+        } else {
158
             // We diverge from the WPAD spec here in that we don't walk the
159
             // hosts's FQDN, stripping components until we hit a TLD.  Doing so
160
             // is dangerous in the face of an incomplete list of TLDs, and TLDs
161
             // get added over time.  We could consider doing only a single
162
             // substitution of the first component, if that proves to help
163
             // compatibility.
164
-            tempString.AssignLiteral("http://wpad/wpad.dat");
165
+            if (mSystemProxySettings)
166
+                mSystemProxySettings->GetPACURI(tempString);
167
+            else
168
+                tempString.AssignLiteral("http://wpad/wpad.dat");
169
+        }
170
+        if (!tempString.IsEmpty()) {
171
+            ConfigureFromPAC(tempString);
172
         }
173
-        ConfigureFromPAC(tempString);
174
     }
175
 }
176
 
177
@@ -901,13 +913,16 @@
178
             return NS_ERROR_OUT_OF_MEMORY;
179
     }
180
 
181
-    mFailedProxies.Clear();
182
-
183
     nsCOMPtr<nsIURI> pacURI;
184
     nsresult rv = NS_NewURI(getter_AddRefs(pacURI), spec);
185
     if (NS_FAILED(rv))
186
         return rv;
187
 
188
+    if (mPACMan->IsPACURI(pacURI))
189
+        return NS_OK;
190
+
191
+    mFailedProxies.Clear();
192
+
193
     return mPACMan->LoadPACFromURI(pacURI);
194
 }
195
 
196
@@ -917,8 +932,10 @@
197
                                             nsresult       aStatus,
198
                                             nsIProxyInfo **aResult)
199
 {
200
-    // We only support failover when a PAC file is configured.
201
-    if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD)
202
+    // We only support failover when a PAC file is configured, either
203
+    // directly or via system settings
204
+    if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD &&
205
+        mProxyConfig != eProxyConfig_System)
206
         return NS_ERROR_NOT_AVAILABLE;
207
 
208
     // Verify that |aProxy| is one of our nsProxyInfo objects.
209
@@ -1214,15 +1231,37 @@
210
     if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
211
         return NS_OK;  // Can't proxy this (filters may not override)
212
 
213
+    if (mSystemProxySettings) {
214
+        nsCAutoString PACURI;
215
+        if (NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) &&
216
+            !PACURI.IsEmpty()) {
217
+            // Switch to new PAC file if that setting has changed. If the setting
218
+            // hasn't changed, ConfigureFromPAC will exit early.
219
+            nsresult rv = ConfigureFromPAC(PACURI);
220
+            if (NS_FAILED(rv))
221
+                return rv;
222
+        } else {
223
+            nsCAutoString proxy;
224
+            nsresult rv = mSystemProxySettings->GetProxyForURI(uri, proxy);
225
+            if (NS_SUCCEEDED(rv)) {
226
+                ProcessPACString(proxy, result);
227
+                return NS_OK;
228
+            }
229
+            // no proxy, stop search
230
+            return NS_OK;
231
+        }
232
+    }
233
+
234
     // if proxies are enabled and this host:port combo is supposed to use a
235
     // proxy, check for a proxy.
236
     if (mProxyConfig == eProxyConfig_Direct ||
237
             (mProxyConfig == eProxyConfig_Manual &&
238
              !CanUseProxy(uri, info.defaultPort)))
239
         return NS_OK;
240
-    
241
+
242
     // Proxy auto config magic...
243
-    if (mProxyConfig == eProxyConfig_PAC || mProxyConfig == eProxyConfig_WPAD) {
244
+    if (mProxyConfig == eProxyConfig_PAC || mProxyConfig == eProxyConfig_WPAD ||
245
+        mProxyConfig == eProxyConfig_System) {
246
         // Do not query PAC now.
247
         *usePAC = PR_TRUE;
248
         return NS_OK;
249
--- netwerk/base/src/nsProtocolProxyService.h
250
+++ netwerk/base/src/nsProtocolProxyService.h
251
@@ -48,6 +48,7 @@
252
 #include "nsPIProtocolProxyService.h"
253
 #include "nsIProtocolProxyFilter.h"
254
 #include "nsIProxyAutoConfig.h"
255
+#include "nsISystemProxySettings.h"
256
 #include "nsIProxyInfo.h"
257
 #include "nsIObserver.h"
258
 #include "nsDataHashtable.h"
259
@@ -310,6 +311,7 @@
260
         eProxyConfig_PAC,
261
         eProxyConfig_Direct4x,
262
         eProxyConfig_WPAD,
263
+        eProxyConfig_System, // use system proxy settings if available, otherwise WPAD
264
         eProxyConfig_Last
265
     };
266
 
267
@@ -371,6 +373,7 @@
268
     PRBool                       mSOCKSProxyRemoteDNS;
269
 
270
     nsRefPtr<nsPACMan>           mPACMan;  // non-null if we are using PAC
271
+    nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
272
 
273
     PRTime                       mSessionStart;
274
     nsFailedProxyTable           mFailedProxies;
275
Index: Makefile.in
276
===================================================================
277
RCS file: /cvsroot/mozilla/Makefile.in,v
278
retrieving revision 1.299.2.18
279
diff -u -p -6 -r1.299.2.18 Makefile.in
280
--- Makefile.in 14 Sep 2006 18:07:02 -0000  1.299.2.18
281
+++ Makefile.in 27 Nov 2006 19:04:14 -0000
282
@@ -282,12 +282,13 @@ tier_50_dirs  += directory/xpcom
283
 endif
284
 
285
 ifndef MINIMO
286
 ifdef MOZ_XUL_APP
287
 ifdef MOZ_ENABLE_GTK2
288
 tier_50_dirs    += toolkit/components/gnome
289
+tier_50_dirs    += toolkit/components/unixproxy
290
 endif
291
 endif
292
 endif
293
 
294
 ifdef MOZ_LEAKY
295
 tier_50_dirs        += tools/leaky
296
--- toolkit/components/unixproxy/Makefile.in.orig   2006-11-27 21:25:50.000000000 +0100
297
+++ toolkit/components/unixproxy/Makefile.in    2006-11-27 21:26:18.000000000 +0100
298
@@ -0,0 +1,67 @@
299
+# ***** BEGIN LICENSE BLOCK *****
300
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
301
+#
302
+# The contents of this file are subject to the Mozilla Public License Version
303
+# 1.1 (the "License"); you may not use this file except in compliance with
304
+# the License. You may obtain a copy of the License at
305
+# http://www.mozilla.org/MPL/
306
+#
307
+# Software distributed under the License is distributed on an "AS IS" basis,
308
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
309
+# for the specific language governing rights and limitations under the
310
+# License.
311
+#
312
+# The Original Code is the Mozilla GNOME integration code.
313
+#
314
+# The Initial Developer of the Original Code is
315
+# IBM Corporation.
316
+# Portions created by the Initial Developer are Copyright (C) 2004
317
+# the Initial Developer. All Rights Reserved.
318
+#
319
+# Contributor(s):
320
+#  Brian Ryner <bryner@brianryner.com>
321
+#
322
+# Alternatively, the contents of this file may be used under the terms of
323
+# either the GNU General Public License Version 2 or later (the "GPL"), or
324
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
325
+# in which case the provisions of the GPL or the LGPL are applicable instead
326
+# of those above. If you wish to allow use of your version of this file only
327
+# under the terms of either the GPL or the LGPL, and not to allow others to
328
+# use your version of this file under the terms of the MPL, indicate your
329
+# decision by deleting the provisions above and replace them with the notice
330
+# and other provisions required by the GPL or the LGPL. If you do not delete
331
+# the provisions above, a recipient may use your version of this file under
332
+# the terms of any one of the MPL, the GPL or the LGPL.
333
+#
334
+# ***** END LICENSE BLOCK *****
335
+
336
+DEPTH     = ../../..
337
+topsrcdir = @top_srcdir@
338
+srcdir    = @srcdir@
339
+VPATH     = @srcdir@
340
+
341
+include $(DEPTH)/config/autoconf.mk
342
+
343
+MODULE          = unixproxy
344
+MOZILLA_INTERNAL_API = 1
345
+
346
+REQUIRES = \
347
+        xpcom \
348
+        string \
349
+        necko \
350
+        mozgnome \
351
+        $(NULL)
352
+
353
+CPPSRCS = \
354
+        nsUnixSystemProxySettings.cpp \
355
+        $(NULL)
356
+
357
+LIBRARY_NAME    = unixproxy
358
+IS_COMPONENT    = 1
359
+FORCE_SHARED_LIB = 1
360
+
361
+EXTRA_DSO_LDOPTS += \
362
+   $(MOZ_COMPONENT_LIBS) \
363
+   $(NULL)
364
+
365
+include $(topsrcdir)/config/rules.mk
366
Index: toolkit/components/gnome/nsGConfService.cpp
367
===================================================================
368
RCS file: /cvsroot/mozilla/toolkit/components/gnome/Attic/nsGConfService.cpp,v
369
retrieving revision 1.2
370
diff -u -p -6 -r1.2 nsGConfService.cpp
371
--- toolkit/components/gnome/nsGConfService.cpp 15 Jul 2004 22:51:19 -0000  1.2
372
+++ toolkit/components/gnome/nsGConfService.cpp 29 May 2007 05:42:27 -0000
373
@@ -121,12 +121,70 @@ nsGConfService::GetFloat(const nsACStrin
374
     return NS_ERROR_FAILURE;
375
   }
376
 
377
   return NS_OK;
378
 }
379
 
380
+class StringListEnumerator : public nsIUTF8StringEnumerator
381
+{
382
+public:
383
+  NS_DECL_ISUPPORTS
384
+  NS_DECL_NSIUTF8STRINGENUMERATOR
385
+
386
+  StringListEnumerator(GSList* aList) : mList(aList), mNext(aList) {}
387
+  virtual ~StringListEnumerator() {
388
+    g_slist_free(mList);
389
+  }
390
+
391
+private:
392
+  GSList* mList;
393
+  GSList* mNext;
394
+};
395
+
396
+NS_IMPL_ISUPPORTS1(StringListEnumerator, nsIUTF8StringEnumerator)
397
+
398
+NS_IMETHODIMP
399
+StringListEnumerator::HasMore(PRBool* aResult)
400
+{
401
+  NS_PRECONDITION(aResult, "null ptr");
402
+  *aResult = mNext != nsnull;
403
+  return NS_OK;
404
+}
405
+
406
+NS_IMETHODIMP
407
+StringListEnumerator::GetNext(nsACString& aResult)
408
+{
409
+  if (!mNext)
410
+    return NS_ERROR_UNEXPECTED;
411
+  aResult.Assign(NS_STATIC_CAST(char*, mNext->data));
412
+  mNext = mNext->next;
413
+  return NS_OK;
414
+}
415
+
416
+NS_IMETHODIMP
417
+nsGConfService::GetStringList(const nsACString &aKey,
418
+                              nsIUTF8StringEnumerator** aResult)
419
+{
420
+  GError* error = nsnull;
421
+  GSList* list = gconf_client_get_list(mClient, PromiseFlatCString(aKey).get(),
422
+                                       GCONF_VALUE_STRING, &error);
423
+  if (error) {
424
+    g_error_free(error);
425
+    return NS_ERROR_FAILURE;
426
+  }
427
+
428
+  StringListEnumerator* enumerator = new StringListEnumerator(list);
429
+  if (!enumerator) {
430
+    g_slist_free(list);
431
+    return NS_ERROR_OUT_OF_MEMORY;
432
+  }
433
+
434
+  NS_ADDREF(*aResult = enumerator);
435
+  return NS_OK;
436
+}
437
+
438
 NS_IMETHODIMP
439
 nsGConfService::SetBool(const nsACString &aKey, PRBool aValue)
440
 {
441
   PRBool res = gconf_client_set_bool(mClient, PromiseFlatCString(aKey).get(),
442
                                      aValue, nsnull);
443
 
444
Index: toolkit/components/gnome/nsIGConfService.idl
445
===================================================================
446
RCS file: /cvsroot/mozilla/toolkit/components/gnome/Attic/nsIGConfService.idl,v
447
retrieving revision 1.2
448
diff -u -p -6 -r1.2 nsIGConfService.idl
449
--- toolkit/components/gnome/nsIGConfService.idl    15 Jul 2004 22:51:19 -0000  1.2
450
+++ toolkit/components/gnome/nsIGConfService.idl    29 May 2007 05:42:52 -0000
451
@@ -34,21 +34,23 @@
452
  * the provisions above, a recipient may use your version of this file under
453
  * the terms of any one of the MPL, the GPL or the LGPL.
454
  *
455
  * ***** END LICENSE BLOCK ***** */
456
 
457
 #include "nsISupports.idl"
458
+#include "nsIStringEnumerator.idl"
459
 
460
 [scriptable, uuid(01ac7b2e-c07c-465f-b35c-542eaef420a9)]
461
 interface nsIGConfService : nsISupports
462
 {
463
   /* Basic registry access */
464
   boolean       getBool(in AUTF8String key);
465
   AUTF8String   getString(in AUTF8String key);
466
   long          getInt(in AUTF8String key);
467
   float         getFloat(in AUTF8String key);
468
+  nsIUTF8StringEnumerator getStringList(in AUTF8String key);
469
 
470
   void setBool(in AUTF8String key, in boolean value);
471
   void setString(in AUTF8String key, in AUTF8String value);
472
   void setInt(in AUTF8String key, in long value);
473
   void setFloat(in AUTF8String key, in float value);
474
 
475
--- toolkit/components/unixproxy/nsUnixSystemProxySettings.cpp.orig 2007-05-29 07:45:58.000000000 +0200
476
+++ toolkit/components/unixproxy/nsUnixSystemProxySettings.cpp  2007-05-29 08:37:45.000000000 +0200
477
@@ -0,0 +1,422 @@
478
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
479
+/* ***** BEGIN LICENSE BLOCK *****
480
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
481
+ *
482
+ * The contents of this file are subject to the Mozilla Public License Version
483
+ * 1.1 (the "License"); you may not use this file except in compliance with
484
+ * the License. You may obtain a copy of the License at
485
+ * http://www.mozilla.org/MPL/
486
+ *
487
+ * Software distributed under the License is distributed on an "AS IS" basis,
488
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
489
+ * for the specific language governing rights and limitations under the
490
+ * License.
491
+ *
492
+ * The Original Code is mozilla.org code.
493
+ *
494
+ * The Initial Developer of the Original Code is
495
+ * Netscape Communications Corporation.
496
+ * Portions created by the Initial Developer are Copyright (C) 1998
497
+ * the Initial Developer. All Rights Reserved.
498
+ *
499
+ * Contributor(s):
500
+ *    Robert O'Callahan (rocallahan@novell.com)
501
+ *
502
+ * Alternatively, the contents of this file may be used under the terms of
503
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
504
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
505
+ * in which case the provisions of the GPL or the LGPL are applicable instead
506
+ * of those above. If you wish to allow use of your version of this file only
507
+ * under the terms of either the GPL or the LGPL, and not to allow others to
508
+ * use your version of this file under the terms of the MPL, indicate your
509
+ * decision by deleting the provisions above and replace them with the notice
510
+ * and other provisions required by the GPL or the LGPL. If you do not delete
511
+ * the provisions above, a recipient may use your version of this file under
512
+ * the terms of any one of the MPL, the GPL or the LGPL.
513
+ *
514
+ * ***** END LICENSE BLOCK ***** */
515
+
516
+#include "nsISystemProxySettings.h"
517
+#include "nsIGenericFactory.h"
518
+#include "nsIServiceManager.h"
519
+#include "nsIGConfService.h"
520
+#include "nsIURI.h"
521
+#include "nsReadableUtils.h"
522
+#include "nsArray.h"
523
+#include "prnetdb.h"
524
+#include "prenv.h"
525
+#include "nsPrintfCString.h"
526
+#include "nsNetUtil.h"
527
+
528
+class nsUnixSystemProxySettings : public nsISystemProxySettings {
529
+public:
530
+  NS_DECL_ISUPPORTS
531
+  NS_DECL_NSISYSTEMPROXYSETTINGS
532
+
533
+  nsUnixSystemProxySettings() {}
534
+  nsresult Init();
535
+
536
+private:
537
+  ~nsUnixSystemProxySettings() {}
538
+  
539
+  nsCOMPtr<nsIGConfService> mGConf;
540
+};
541
+
542
+NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
543
+
544
+nsresult
545
+nsUnixSystemProxySettings::Init()
546
+{
547
+  // If this is a GNOME session, load gconf and try to use its preferences.
548
+  // If gconf is not available (which would be stupid) we'll proceed as if this
549
+  // was not a GNOME session, using *_PROXY environment variables.
550
+  const char* sessionType = PR_GetEnv("DESKTOP_SESSION");
551
+  if (sessionType && !strcmp(sessionType, "gnome")) {
552
+    mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
553
+  }
554
+  return NS_OK;
555
+}
556
+
557
+static PRBool
558
+IsProxyMode(nsIGConfService* aGConf, const char* aMode)
559
+{
560
+  nsCAutoString mode;
561
+  return NS_SUCCEEDED(aGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/mode"), mode)) &&
562
+      mode.EqualsASCII(aMode);
563
+}
564
+
565
+nsresult
566
+nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
567
+{
568
+  if (!mGConf || !IsProxyMode(mGConf, "auto"))
569
+    return NS_ERROR_FAILURE;
570
+  return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"),
571
+                           aResult);
572
+}
573
+
574
+static PRBool
575
+IsInNoProxyList(const nsACString& aHost, PRInt32 aPort, const char* noProxyVal)
576
+{
577
+  NS_ASSERTION(aPort >= 0, "Negative port?");
578
+  
579
+  nsCAutoString noProxy(noProxyVal);
580
+  if (noProxy.EqualsLiteral("*"))
581
+    return PR_TRUE;
582
+    
583
+  noProxy.StripWhitespace();
584
+  
585
+  nsReadingIterator<char> pos;
586
+  nsReadingIterator<char> end;
587
+  noProxy.BeginReading(pos);
588
+  noProxy.EndReading(end);
589
+  while (pos != end) {
590
+    nsReadingIterator<char> last = pos;
591
+    nsReadingIterator<char> nextPos;
592
+    if (FindCharInReadable(',', last, end)) {
593
+      nextPos = last;
594
+      ++nextPos;
595
+    } else {
596
+      last = end;
597
+      nextPos = end;
598
+    }
599
+    
600
+    nsReadingIterator<char> colon = pos;
601
+    PRInt32 port = -1;
602
+    if (FindCharInReadable(':', colon, last)) {
603
+      ++colon;
604
+      nsDependentCSubstring portStr(colon, last);
605
+      nsCAutoString portStr2(portStr);
606
+      PRInt32 err;
607
+      port = portStr2.ToInteger(&err);
608
+      if (err != 0) {
609
+        port = -2; // don't match any port, so we ignore this pattern
610
+      }
611
+      --colon;
612
+    } else {
613
+      colon = last;
614
+    }
615
+    
616
+    if (port == -1 || port == aPort) {
617
+      nsDependentCSubstring hostStr(pos, colon);
618
+      if (StringEndsWith(aHost, hostStr, nsCaseInsensitiveCStringComparator()))
619
+        return PR_TRUE;
620
+    }
621
+    
622
+    pos = nextPos;
623
+  }
624
+  
625
+  return PR_FALSE;
626
+}
627
+
628
+static void SetProxyResult(const char* aType, const nsACString& aHost,
629
+                               PRInt32 aPort, nsACString& aResult)
630
+{
631
+  aResult.AppendASCII(aType);
632
+  aResult.Append(' ');
633
+  aResult.Append(aHost);
634
+  aResult.Append(':');
635
+  aResult.Append(nsPrintfCString("%d", aPort));
636
+}
637
+
638
+static nsresult
639
+GetProxyForURIFromEnvironment(const nsACString& aScheme,
640
+                              const nsACString& aHost,
641
+                              PRInt32 aPort,
642
+                              nsACString& aResult)
643
+{
644
+  nsCAutoString envVar;
645
+  envVar.Append(aScheme);
646
+  envVar.AppendLiteral("_proxy");
647
+  const char* proxyVal = PR_GetEnv(envVar.get());
648
+  if (!proxyVal) {
649
+    proxyVal = PR_GetEnv("all_proxy");
650
+    if (!proxyVal) {
651
+      // Return failure so that the caller can detect the failure and
652
+      // fall back to other proxy detection (e.g., WPAD)
653
+      return NS_ERROR_FAILURE;
654
+    }
655
+  }
656
+  
657
+  const char* noProxyVal = PR_GetEnv("no_proxy");
658
+  if (noProxyVal && IsInNoProxyList(aHost, aPort, noProxyVal)) {
659
+    aResult.AppendLiteral("DIRECT");
660
+    return NS_OK;
661
+  }
662
+  
663
+  // Use our URI parser to crack the proxy URI
664
+  nsCOMPtr<nsIURI> proxyURI;
665
+  nsresult rv = NS_NewURI(getter_AddRefs(proxyURI), proxyVal);
666
+  if (NS_FAILED(rv))
667
+    return rv;
668
+
669
+  // Is there a way to specify "socks://" or something in these environment
670
+  // variables? I can't find any documentation.
671
+  PRBool isHTTP;
672
+  rv = proxyURI->SchemeIs("http", &isHTTP);
673
+  if (NS_FAILED(rv))
674
+    return rv;
675
+  if (!isHTTP)
676
+    return NS_ERROR_FAILURE;
677
+
678
+  nsCAutoString proxyHost;
679
+  rv = proxyURI->GetHost(proxyHost);
680
+  if (NS_FAILED(rv))
681
+    return rv;
682
+  PRInt32 proxyPort;
683
+  rv = proxyURI->GetPort(&proxyPort);
684
+  if (NS_FAILED(rv))
685
+    return rv;
686
+
687
+  SetProxyResult("PROXY", proxyHost, proxyPort, aResult);
688
+  return NS_OK;
689
+}
690
+
691
+static nsresult
692
+SetProxyResultFromGConf(nsIGConfService* aGConf, const char* aKeyBase,
693
+                        const char* aType, nsACString& aResult)
694
+{
695
+  nsCAutoString hostKey;
696
+  hostKey.AppendASCII(aKeyBase);
697
+  hostKey.AppendLiteral("host");
698
+  nsCAutoString host;
699
+  nsresult rv = aGConf->GetString(hostKey, host);
700
+  if (NS_FAILED(rv))
701
+    return rv;
702
+  if (host.IsEmpty())
703
+    return NS_ERROR_FAILURE;
704
+  
705
+  nsCAutoString portKey;
706
+  portKey.AppendASCII(aKeyBase);
707
+  portKey.AppendLiteral("port");
708
+  PRInt32 port;
709
+  rv = aGConf->GetInt(portKey, &port);
710
+  if (NS_FAILED(rv))
711
+    return rv;
712
+    
713
+  SetProxyResult(aType, host, port, aResult);
714
+  return NS_OK;
715
+}
716
+
717
+/* copied from nsProtocolProxyService.cpp --- we should share this! */
718
+static void
719
+proxy_MaskIPv6Addr(PRIPv6Addr &addr, PRUint16 mask_len)
720
+{
721
+    if (mask_len == 128)
722
+        return;
723
+
724
+    if (mask_len > 96) {
725
+        addr.pr_s6_addr32[3] = PR_htonl(
726
+                PR_ntohl(addr.pr_s6_addr32[3]) & (~0L << (128 - mask_len)));
727
+    }
728
+    else if (mask_len > 64) {
729
+        addr.pr_s6_addr32[3] = 0;
730
+        addr.pr_s6_addr32[2] = PR_htonl(
731
+                PR_ntohl(addr.pr_s6_addr32[2]) & (~0L << (96 - mask_len)));
732
+    }
733
+    else if (mask_len > 32) {
734
+        addr.pr_s6_addr32[3] = 0;
735
+        addr.pr_s6_addr32[2] = 0;
736
+        addr.pr_s6_addr32[1] = PR_htonl(
737
+                PR_ntohl(addr.pr_s6_addr32[1]) & (~0L << (64 - mask_len)));
738
+    }
739
+    else {
740
+        addr.pr_s6_addr32[3] = 0;
741
+        addr.pr_s6_addr32[2] = 0;
742
+        addr.pr_s6_addr32[1] = 0;
743
+        addr.pr_s6_addr32[0] = PR_htonl(
744
+                PR_ntohl(addr.pr_s6_addr32[0]) & (~0L << (32 - mask_len)));
745
+    }
746
+}
747
+
748
+static PRBool ConvertToIPV6Addr(const nsACString& aName,
749
+                                PRIPv6Addr* aAddr)
750
+{
751
+  PRNetAddr addr;
752
+  if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS)
753
+    return PR_FALSE;
754
+
755
+  PRIPv6Addr ipv6;
756
+  // convert parsed address to IPv6
757
+  if (addr.raw.family == PR_AF_INET) {
758
+    // convert to IPv4-mapped address
759
+    PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &ipv6);
760
+  } else if (addr.raw.family == PR_AF_INET6) {
761
+    // copy the address
762
+    memcpy(&ipv6, &addr.ipv6.ip, sizeof(PRIPv6Addr));
763
+  } else {
764
+    return PR_FALSE;
765
+  }
766
+  
767
+  return PR_TRUE;
768
+}
769
+
770
+static PRBool GConfIgnoreHost(const nsACString& aIgnore,
771
+                              const nsACString& aHost)
772
+{
773
+  if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator()))
774
+    return PR_TRUE;
775
+
776
+  if (StringBeginsWith(aIgnore, NS_LITERAL_CSTRING("*")) &&
777
+      StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1),
778
+                     nsCaseInsensitiveCStringComparator()))
779
+    return PR_TRUE;
780
+
781
+  PRInt32 mask = 128;
782
+  nsReadingIterator<char> start;
783
+  nsReadingIterator<char> slash;
784
+  nsReadingIterator<char> end;
785
+  aIgnore.BeginReading(start);
786
+  aIgnore.BeginReading(slash);
787
+  aIgnore.EndReading(end);
788
+  if (FindCharInReadable('/', slash, end)) {
789
+    ++slash;
790
+    nsDependentCSubstring maskStr(slash, end);
791
+    nsCAutoString maskStr2(maskStr);
792
+    PRInt32 err;
793
+    mask = maskStr2.ToInteger(&err);
794
+    if (err != 0) {
795
+      mask = 128;
796
+    }
797
+    --slash;
798
+  } else {
799
+    slash = end;
800
+  }
801
+
802
+  PRIPv6Addr ignoreAddr, hostAddr;
803
+  if (!ConvertToIPV6Addr(aIgnore, &ignoreAddr) ||
804
+      !ConvertToIPV6Addr(aHost, &hostAddr))
805
+    return PR_FALSE;
806
+
807
+  proxy_MaskIPv6Addr(ignoreAddr, mask);
808
+  proxy_MaskIPv6Addr(hostAddr, mask);
809
+  
810
+  return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0;
811
+}
812
+
813
+static nsresult
814
+GetProxyForURIFromGConf(nsIGConfService* aGConf,
815
+                        const nsACString& aScheme,
816
+                        const nsACString& aHost,
817
+                        PRInt32 aPort,
818
+                        nsACString& aResult)
819
+{
820
+  if (!IsProxyMode(aGConf, "manual")) {
821
+    aResult.AppendLiteral("DIRECT");
822
+    return NS_OK;
823
+  }
824
+  
825
+  nsCOMPtr<nsIUTF8StringEnumerator> ignoreList;
826
+  if (NS_SUCCEEDED(aGConf->GetStringList(NS_LITERAL_CSTRING("/system/http_proxy/ignore_hosts"),
827
+                                         getter_AddRefs(ignoreList))) && ignoreList) {
828
+    while (PR_TRUE) {
829
+      PRBool hasMore;
830
+      if (NS_FAILED(ignoreList->HasMore(&hasMore)) || !hasMore)
831
+        break;
832
+      nsCAutoString s;
833
+      if (NS_SUCCEEDED(ignoreList->GetNext(s))) {
834
+        if (GConfIgnoreHost(s, aHost)) {
835
+          aResult.AppendLiteral("DIRECT");
836
+          return NS_OK;
837
+        }
838
+      }
839
+    }
840
+  }
841
+  
842
+  nsresult rv = SetProxyResultFromGConf(aGConf, "/system/proxy/socks_", "SOCKS", aResult);
843
+  if (NS_SUCCEEDED(rv))
844
+    return rv;
845
+  
846
+  if (aScheme.LowerCaseEqualsLiteral("http")) {
847
+    rv = SetProxyResultFromGConf(aGConf, "/system/http_proxy/", "PROXY", aResult);
848
+  } else if (aScheme.LowerCaseEqualsLiteral("https")) {
849
+    rv = SetProxyResultFromGConf(aGConf, "/system/proxy/secure_", "PROXY", aResult);
850
+  } else if (aScheme.LowerCaseEqualsLiteral("ftp")) {
851
+    rv = SetProxyResultFromGConf(aGConf, "/system/proxy/ftp_", "PROXY", aResult);
852
+  } else {
853
+    rv = NS_ERROR_FAILURE;
854
+  }
855
+  
856
+  if (NS_FAILED(rv)) {
857
+    aResult.AppendLiteral("DIRECT");
858
+  }
859
+  return NS_OK;
860
+}
861
+
862
+nsresult
863
+nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
864
+{
865
+  nsCAutoString scheme;
866
+  nsresult rv = aURI->GetScheme(scheme);
867
+  if (NS_FAILED(rv))
868
+    return rv;
869
+
870
+  nsCAutoString host;
871
+  rv = aURI->GetHost(host);
872
+  if (NS_FAILED(rv))
873
+    return rv;
874
+
875
+  PRInt32 port;
876
+  rv = aURI->GetPort(&port);
877
+  if (NS_FAILED(rv))
878
+    return rv;
879
+
880
+  if (!mGConf)
881
+    return GetProxyForURIFromEnvironment(scheme, host, port, aResult);
882
+
883
+  return GetProxyForURIFromGConf(mGConf, scheme, host, port, aResult);
884
+}
885
+
886
+#define NS_UNIXSYSTEMPROXYSERVICE_CID  /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
887
+     { 0x0fa3158c, 0xd5a7, 0x43de, \
888
+       {0x91, 0x81, 0xa2, 0x85, 0xe7, 0x4c, 0xf1, 0xd4 } }
889
+
890
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUnixSystemProxySettings, Init)
891
+
892
+static const nsModuleComponentInfo components[] = {
893
+  { "Unix System Proxy Settings Service",
894
+    NS_UNIXSYSTEMPROXYSERVICE_CID,
895
+    NS_SYSTEMPROXYSETTINGS_CONTRACTID,
896
+    nsUnixSystemProxySettingsConstructor }
897
+};
898
+
899
+NS_IMPL_NSGETMODULE(unixproxy, components)
900