1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/proxydetect.h"
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/win32.h"
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <shlobj.h>
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef HAVE_CONFIG_H
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "config.h"
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef OSX
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <SystemConfiguration/SystemConfiguration.h>
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <CoreFoundation/CoreFoundation.h>
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <CoreServices/CoreServices.h>
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <Security/Security.h>
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "macconversion.h"
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <map>
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/fileutils.h"
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/httpcommon.h"
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/httpcommon-inl.h"
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/pathutils.h"
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/stringutils.h"
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define _TRY_WINHTTP 1
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define _TRY_JSPROXY 0
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define _TRY_WM_FINDPROXY 0
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define _TRY_IE_LAN_SETTINGS 1
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// For all platforms try Firefox.
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define _TRY_FIREFOX 1
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Use profiles.ini to find the correct profile for this user.
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// If not set, we'll just look for the default one.
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define USE_FIREFOX_PROFILES_INI 1
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const size_t kMaxLineLength = 1024;
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const char kFirefoxPattern[] = "Firefox";
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const char kInternetExplorerPattern[] = "MSIE";
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstruct StringMap {
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void Add(const char * name, const char * value) { map_[name] = value; }
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const std::string& Get(const char * name, const char * def = "") const {
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::map<std::string, std::string>::const_iterator it =
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        map_.find(name);
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (it != map_.end())
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return it->second;
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    def_ = def;
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return def_;
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool IsSet(const char * name) const {
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return (map_.find(name) != map_.end());
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private:
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::map<std::string, std::string> map_;
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  mutable std::string def_;
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochenum UserAgent {
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UA_FIREFOX,
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UA_INTERNETEXPLORER,
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UA_OTHER,
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UA_UNKNOWN
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if _TRY_WINHTTP
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//#include <winhttp.h>
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Note: From winhttp.h
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char WINHTTP[] = "winhttp";
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef LPVOID HINTERNET;
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef struct {
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD  dwAccessType;      // see WINHTTP_ACCESS_* types below
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LPWSTR lpszProxy;         // proxy server list
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LPWSTR lpszProxyBypass;   // proxy bypass list
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} WINHTTP_PROXY_INFO, * LPWINHTTP_PROXY_INFO;
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef struct {
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD   dwFlags;
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD   dwAutoDetectFlags;
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LPCWSTR lpszAutoConfigUrl;
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LPVOID  lpvReserved;
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD   dwReserved;
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  BOOL    fAutoLogonIfChallenged;
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} WINHTTP_AUTOPROXY_OPTIONS;
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef struct {
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  BOOL    fAutoDetect;
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LPWSTR  lpszAutoConfigUrl;
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LPWSTR  lpszProxy;
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LPWSTR  lpszProxyBypass;
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochextern "C" {
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  typedef HINTERNET (WINAPI * pfnWinHttpOpen)
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      (
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN LPCWSTR pwszUserAgent,
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN DWORD   dwAccessType,
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN LPCWSTR pwszProxyName   OPTIONAL,
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN LPCWSTR pwszProxyBypass OPTIONAL,
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN DWORD   dwFlags
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          );
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  typedef BOOL (STDAPICALLTYPE * pfnWinHttpCloseHandle)
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      (
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN HINTERNET hInternet
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          );
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetProxyForUrl)
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      (
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN  HINTERNET                   hSession,
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN  LPCWSTR                     lpcwszUrl,
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN  WINHTTP_AUTOPROXY_OPTIONS * pAutoProxyOptions,
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          OUT WINHTTP_PROXY_INFO *        pProxyInfo
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          );
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetIEProxyConfig)
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      (
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          );
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // extern "C"
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_AUTOPROXY_AUTO_DETECT           0x00000001
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_AUTOPROXY_CONFIG_URL            0x00000002
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_AUTOPROXY_RUN_INPROCESS         0x00010000
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY   0x00020000
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_AUTO_DETECT_TYPE_DHCP           0x00000001
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_AUTO_DETECT_TYPE_DNS_A          0x00000002
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY               0
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_ACCESS_TYPE_NO_PROXY                    1
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_ACCESS_TYPE_NAMED_PROXY                 3
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_NO_PROXY_NAME     NULL
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WINHTTP_NO_PROXY_BYPASS   NULL
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // _TRY_WINHTTP
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if _TRY_JSPROXY
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochextern "C" {
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  typedef BOOL (STDAPICALLTYPE * pfnInternetGetProxyInfo)
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      (
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          LPCSTR lpszUrl,
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          DWORD dwUrlLength,
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          LPSTR lpszUrlHostName,
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          DWORD dwUrlHostNameLength,
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          LPSTR * lplpszProxyHostName,
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          LPDWORD lpdwProxyHostNameLength
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          );
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // extern "C"
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // _TRY_JSPROXY
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if _TRY_WM_FINDPROXY
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <comutil.h>
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <wmnetsourcecreator.h>
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <wmsinternaladminnetsource.h>
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // _TRY_WM_FINDPROXY
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if _TRY_IE_LAN_SETTINGS
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <wininet.h>
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <string>
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // _TRY_IE_LAN_SETTINGS
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base {
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Utility Functions
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _UNICODE
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef std::wstring tstring;
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string Utf8String(const tstring& str) { return ToUtf8(str); }
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else  // !_UNICODE
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef std::string tstring;
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string Utf8String(const tstring& str) { return str; }
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // !_UNICODE
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool ProxyItemMatch(const Url<char>& url, char * item, size_t len) {
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // hostname:443
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (char * port = ::strchr(item, ':')) {
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    *port++ = '\0';
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (url.port() != atol(port)) {
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // A.B.C.D or A.B.C.D/24
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int a, b, c, d, m;
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int match = sscanf(item, "%d.%d.%d.%d/%d", &a, &b, &c, &d, &m);
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (match >= 4) {
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    uint32 ip = ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) |
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        (d & 0xFF);
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((match < 5) || (m > 32))
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      m = 32;
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    else if (m < 0)
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      m = 0;
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    uint32 mask = (m == 0) ? 0 : (~0UL) << (32 - m);
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SocketAddress addr(url.host(), 0);
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return !addr.IsUnresolved() && ((addr.ip() & mask) == (ip & mask));
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // .foo.com
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (*item == '.') {
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    size_t hostlen = url.host().length();
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return (hostlen > len)
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        && (stricmp(url.host().c_str() + (hostlen - len), item) == 0);
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // localhost or www.*.com
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!string_match(url.host().c_str(), item))
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool ProxyListMatch(const Url<char>& url, const std::string& proxy_list,
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                    char sep) {
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const size_t BUFSIZE = 256;
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  char buffer[BUFSIZE];
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const char* list = proxy_list.c_str();
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (*list) {
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Remove leading space
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (isspace(*list)) {
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ++list;
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Break on separator
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    size_t len;
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const char * start = list;
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (const char * end = ::strchr(list, sep)) {
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      len = (end - list);
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      list += len + 1;
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      len = strlen(list);
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      list += len;
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Remove trailing space
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    while ((len > 0) && isspace(start[len-1]))
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      --len;
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Check for oversized entry
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (len >= BUFSIZE)
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    memcpy(buffer, start, len);
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    buffer[len] = 0;
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!ProxyItemMatch(url, buffer, len))
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return true;
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return false;
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Better(ProxyType lhs, const ProxyType rhs) {
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // PROXY_NONE, PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const int PROXY_VALUE[5] = { 0, 2, 3, 1 };
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (PROXY_VALUE[lhs] > PROXY_VALUE[rhs]);
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool ParseProxy(const std::string& saddress, ProxyInfo* proxy) {
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const size_t kMaxAddressLength = 1024;
297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Allow semicolon, space, or tab as an address separator
298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const char* const kAddressSeparator = " ;\t";
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ProxyType ptype;
301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string host;
302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint16 port;
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const char* address = saddress.c_str();
305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (*address) {
306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    size_t len;
307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const char * start = address;
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (const char * sep = strchr(address, kAddressSeparator)) {
309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      len = (sep - address);
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      address += len + 1;
311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      while (*address != '\0' && ::strchr(kAddressSeparator, *address)) {
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        address += 1;
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      len = strlen(address);
316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      address += len;
317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (len > kMaxAddressLength - 1) {
320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_WARNING) << "Proxy address too long [" << start << "]";
321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char buffer[kMaxAddressLength];
325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    memcpy(buffer, start, len);
326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    buffer[len] = 0;
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char * colon = ::strchr(buffer, ':');
329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!colon) {
330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_WARNING) << "Proxy address without port [" << buffer << "]";
331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    *colon = 0;
335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char * endptr;
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    port = static_cast<uint16>(strtol(colon + 1, &endptr, 0));
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (*endptr != 0) {
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_WARNING) << "Proxy address with invalid port [" << buffer << "]";
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (char * equals = ::strchr(buffer, '=')) {
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *equals = 0;
344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      host = equals + 1;
345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (_stricmp(buffer, "socks") == 0) {
346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ptype = PROXY_SOCKS5;
347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else if (_stricmp(buffer, "https") == 0) {
348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ptype = PROXY_HTTPS;
349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(LS_WARNING) << "Proxy address with unknown protocol ["
351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                        << buffer << "]";
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ptype = PROXY_UNKNOWN;
353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      host = buffer;
356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ptype = PROXY_UNKNOWN;
357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (Better(ptype, proxy->type)) {
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy->type = ptype;
361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy->address.SetIP(host);
362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy->address.SetPort(port);
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return proxy->type != PROXY_NONE;
367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochUserAgent GetAgent(const char* agent) {
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (agent) {
371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::string agent_str(agent);
372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (agent_str.find(kFirefoxPattern) != std::string::npos) {
373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return UA_FIREFOX;
374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (agent_str.find(kInternetExplorerPattern) != std::string::npos) {
375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return UA_INTERNETEXPLORER;
376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (agent_str.empty()) {
377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return UA_UNKNOWN;
378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return UA_OTHER;
381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool EndsWith(const std::string& a, const std::string& b) {
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (b.size() > a.size()) {
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int result = a.compare(a.size() - b.size(), b.size(), b);
388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result == 0;
389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetFirefoxProfilePath(Pathname* path) {
392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  wchar_t w_path[MAX_PATH];
394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, w_path) !=
395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      S_OK) {
396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "SHGetFolderPath failed";
397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->SetFolder(ToUtf8(w_path, wcslen(w_path)));
400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->AppendFolder("Mozilla");
401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->AppendFolder("Firefox");
402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif OSX
403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FSRef fr;
404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (0 != FSFindFolder(kUserDomain, kApplicationSupportFolderType,
405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                        kCreateFolder, &fr)) {
406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "FSFindFolder failed";
407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  char buffer[NAME_MAX + 1];
410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (0 != FSRefMakePath(&fr, reinterpret_cast<uint8*>(buffer),
411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                         ARRAY_SIZE(buffer))) {
412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "FSRefMakePath failed";
413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->SetFolder(std::string(buffer));
416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->AppendFolder("Firefox");
417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  char* user_home = getenv("HOME");
419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (user_home == NULL) {
420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->SetFolder(std::string(user_home));
423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->AppendFolder(".mozilla");
424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path->AppendFolder("firefox");
425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetDefaultFirefoxProfile(Pathname* profile_path) {
430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(NULL != profile_path);
431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Pathname path;
432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!GetFirefoxProfilePath(&path)) {
433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if USE_FIREFOX_PROFILES_INI
437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // [Profile0]
438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Name=default
439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // IsRelative=1
440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Path=Profiles/2de53ejb.default
441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Default=1
442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Note: we are looking for the first entry with "Default=1", or the last
444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // entry in the file
445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path.SetFilename("profiles.ini");
446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FileStream* fs = Filesystem::OpenFile(path, "r");
447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!fs) {
448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Pathname candidate;
451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool relative = true;
452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string line;
453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (fs->ReadLine(&line) == SR_SUCCESS) {
454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (line.length() == 0) {
455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (line.at(0) == '[') {
458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      relative = true;
459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      candidate.clear();
4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (line.find("IsRelative=") == 0 &&
4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               line.length() >= 12) {
462731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // TODO: The initial Linux public launch revealed a fairly
4633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // high number of machines where IsRelative= did not have anything after
4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // it. Perhaps that is legal profiles.ini syntax?
465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      relative = (line.at(11) != '0');
4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (line.find("Path=") == 0 &&
4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               line.length() >= 6) {
468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (relative) {
469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        candidate = path;
470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        candidate.clear();
472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      candidate.AppendFolder(line.substr(5));
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (line.find("Default=") == 0 &&
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               line.length() >= 9) {
476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if ((line.at(8) != '0') && !candidate.empty()) {
477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  fs->Close();
482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (candidate.empty()) {
483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  profile_path->SetPathname(candidate.pathname());
486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else // !USE_FIREFOX_PROFILES_INI
488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  path.AppendFolder("Profiles");
489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DirectoryIterator* it = Filesystem::IterateDirectory();
490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  it->Iterate(path);
491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string extension(".default");
492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (!EndsWith(it->Name(), extension)) {
493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!it->Next()) {
494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  profile_path->SetPathname(path);
499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  profile->AppendFolder("Profiles");
500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  profile->AppendFolder(it->Name());
501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete it;
502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // !USE_FIREFOX_PROFILES_INI
504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
508f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool ReadFirefoxPrefs(const Pathname& filename,
509f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                      const char * prefix,
510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                      StringMap* settings) {
511f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FileStream* fs = Filesystem::OpenFile(filename, "r");
512f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!fs) {
513f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "Failed to open file: " << filename.pathname();
514f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
515f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
516f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string line;
518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (fs->ReadLine(&line) == SR_SUCCESS) {
519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    size_t prefix_len = strlen(prefix);
520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
521f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Skip blank lines and too long lines.
522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((line.length() == 0) || (line.length() > kMaxLineLength)
523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        || (line.at(0) == '#') || line.compare(0, 2, "/*") == 0
524f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        || line.compare(0, 2, " *") == 0) {
525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      continue;
526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char buffer[kMaxLineLength];
529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    strcpyn(buffer, sizeof(buffer), line.c_str());
530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int nstart = 0, nend = 0, vstart = 0, vend = 0;
531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    sscanf(buffer, "user_pref(\"%n%*[^\"]%n\", %n%*[^)]%n);",
532f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch           &nstart, &nend, &vstart, &vend);
533f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (vend > 0) {
534f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      char* name = buffer + nstart;
535f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      name[nend - nstart] = 0;
536f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if ((vend - vstart >= 2) && (buffer[vstart] == '"')) {
537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        vstart += 1;
538f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        vend -= 1;
539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      char* value = buffer + vstart;
541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      value[vend - vstart] = 0;
542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if ((strncmp(name, prefix, prefix_len) == 0) && *value) {
543f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        settings->Add(name + prefix_len, value);
544f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
545f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
546f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG_F(LS_WARNING) << "Unparsed pref [" << buffer << "]";
547f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
548f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
549f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  fs->Close();
550f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
551f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
552f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
553f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetFirefoxProxySettings(const char* url, ProxyInfo* proxy) {
554f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Url<char> purl(url);
555f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Pathname path;
556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = false;
557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (GetDefaultFirefoxProfile(&path)) {
558f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    StringMap settings;
559f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    path.SetFilename("prefs.js");
560f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ReadFirefoxPrefs(path, "network.proxy.", &settings)) {
561f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      success = true;
562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy->bypass_list =
563f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          settings.Get("no_proxies_on", "localhost, 127.0.0.1");
564f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (settings.Get("type") == "1") {
565f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // User has manually specified a proxy, try to figure out what
566f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // type it is.
567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (ProxyListMatch(purl, proxy->bypass_list.c_str(), ',')) {
568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // Our url is in the list of url's to bypass proxy.
569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else if (settings.Get("share_proxy_settings") == "true") {
570f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->type = PROXY_UNKNOWN;
571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetIP(settings.Get("http"));
572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetPort(atoi(settings.Get("http_port").c_str()));
573f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else if (settings.IsSet("socks")) {
574f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->type = PROXY_SOCKS5;
575f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetIP(settings.Get("socks"));
576f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetPort(atoi(settings.Get("socks_port").c_str()));
577f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else if (settings.IsSet("ssl")) {
578f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->type = PROXY_HTTPS;
579f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetIP(settings.Get("ssl"));
580f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetPort(atoi(settings.Get("ssl_port").c_str()));
581f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else if (settings.IsSet("http")) {
582f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->type = PROXY_HTTPS;
583f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetIP(settings.Get("http"));
584f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetPort(atoi(settings.Get("http_port").c_str()));
585f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
586f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else if (settings.Get("type") == "2") {
587f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Browser is configured to get proxy settings from a given url.
588f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        proxy->autoconfig_url = settings.Get("autoconfig_url").c_str();
589f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else if (settings.Get("type") == "4") {
590f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Browser is configured to auto detect proxy config.
591f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        proxy->autodetect = true;
592f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
593f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // No proxy set.
594f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
595f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
596f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
597f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
598f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
599f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
600f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32  // Windows specific implementation for reading Internet
601f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              // Explorer proxy settings.
602f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
603f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid LogGetProxyFault() {
604f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG_GLEM(LERROR, WINHTTP) << "WinHttpGetProxyForUrl faulted!!";
605f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
606f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
607f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochBOOL MyWinHttpGetProxyForUrl(pfnWinHttpGetProxyForUrl pWHGPFU,
608f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                             HINTERNET hWinHttp, LPCWSTR url,
609f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                             WINHTTP_AUTOPROXY_OPTIONS *options,
610f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                             WINHTTP_PROXY_INFO *info) {
611f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // WinHttpGetProxyForUrl() can call plugins which can crash.
612f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // In the case of McAfee scriptproxy.dll, it does crash in
613f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // older versions. Try to catch crashes here and treat as an
614f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // error.
615f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  BOOL success = FALSE;
616f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
617f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if (_HAS_EXCEPTIONS == 0)
618f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  __try {
619f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = pWHGPFU(hWinHttp, url, options, info);
620f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } __except(EXCEPTION_EXECUTE_HANDLER) {
621f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // This is a separate function to avoid
622f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Visual C++ error 2712 when compiling with C++ EH
623f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LogGetProxyFault();
624f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
625f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
626f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  success = pWHGPFU(hWinHttp, url, options, info);
627f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // (_HAS_EXCEPTIONS == 0)
628f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
629f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
630f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
631f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
632f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool IsDefaultBrowserFirefox() {
633f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  HKEY key;
634f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LONG result = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command",
635f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                             0, KEY_READ, &key);
636f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ERROR_SUCCESS != result)
637f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
638f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
639f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  wchar_t* value = NULL;
640f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD size, type;
641f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  result = RegQueryValueEx(key, L"", 0, &type, NULL, &size);
642f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (REG_SZ != type) {
643f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    result = ERROR_ACCESS_DENIED;  // Any error is fine
644f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (ERROR_SUCCESS == result) {
645f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    value = new wchar_t[size+1];
646f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    BYTE* buffer = reinterpret_cast<BYTE*>(value);
647f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    result = RegQueryValueEx(key, L"", 0, &type, buffer, &size);
648f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
649f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  RegCloseKey(key);
650f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
651f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = false;
652f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ERROR_SUCCESS == result) {
653f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    value[size] = L'\0';
654f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    for (size_t i = 0; i < size; ++i) {
655f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      value[i] = tolowercase(value[i]);
656f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
657f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = (NULL != strstr(value, L"firefox.exe"));
658f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
659f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete [] value;
660f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
661f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
662f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
663f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetWinHttpProxySettings(const char* url, ProxyInfo* proxy) {
664f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  HMODULE winhttp_handle = LoadLibrary(L"winhttp.dll");
665f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (winhttp_handle == NULL) {
666f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "Failed to load winhttp.dll.";
667f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
668f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
669f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG iecfg;
670f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  memset(&iecfg, 0, sizeof(iecfg));
671f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Url<char> purl(url);
672f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  pfnWinHttpGetIEProxyConfig pWHGIEPC =
673f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      reinterpret_cast<pfnWinHttpGetIEProxyConfig>(
674f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          GetProcAddress(winhttp_handle,
675f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                         "WinHttpGetIEProxyConfigForCurrentUser"));
676f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = false;
677f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (pWHGIEPC && pWHGIEPC(&iecfg)) {
678f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // We were read proxy config successfully.
679f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = true;
680f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (iecfg.fAutoDetect) {
681f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy->autodetect = true;
682f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
683f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (iecfg.lpszAutoConfigUrl) {
684f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy->autoconfig_url = ToUtf8(iecfg.lpszAutoConfigUrl);
685f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      GlobalFree(iecfg.lpszAutoConfigUrl);
686f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
687f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (iecfg.lpszProxyBypass) {
688f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy->bypass_list = ToUtf8(iecfg.lpszProxyBypass);
689f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      GlobalFree(iecfg.lpszProxyBypass);
690f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
691f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (iecfg.lpszProxy) {
692f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (!ProxyListMatch(purl, proxy->bypass_list, ';')) {
693f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ParseProxy(ToUtf8(iecfg.lpszProxy), proxy);
694f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
695f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      GlobalFree(iecfg.lpszProxy);
696f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
697f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
698f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FreeLibrary(winhttp_handle);
699f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
700f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
701f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
702f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Uses the WinHTTP API to auto detect proxy for the given url. Firefox and IE
703f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// have slightly different option dialogs for proxy settings. In Firefox,
704f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// either a location of a proxy configuration file can be specified or auto
705f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// detection can be selected. In IE theese two options can be independently
706f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// selected. For the case where both options are selected (only IE) we try to
707f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// fetch the config file first, and if that fails we'll perform an auto
708f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// detection.
709f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
710f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Returns true if we successfully performed an auto detection not depending on
711f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// whether we found a proxy or not. Returns false on error.
712f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool WinHttpAutoDetectProxyForUrl(const char* agent, const char* url,
713f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                  ProxyInfo* proxy) {
714f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Url<char> purl(url);
715f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = true;
716f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  HMODULE winhttp_handle = LoadLibrary(L"winhttp.dll");
717f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (winhttp_handle == NULL) {
718f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "Failed to load winhttp.dll.";
719f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
720f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
721f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  pfnWinHttpOpen pWHO =
722f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      reinterpret_cast<pfnWinHttpOpen>(GetProcAddress(winhttp_handle,
723f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                      "WinHttpOpen"));
724f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  pfnWinHttpCloseHandle pWHCH =
725f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      reinterpret_cast<pfnWinHttpCloseHandle>(
726f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          GetProcAddress(winhttp_handle, "WinHttpCloseHandle"));
727f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  pfnWinHttpGetProxyForUrl pWHGPFU =
728f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      reinterpret_cast<pfnWinHttpGetProxyForUrl>(
729f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          GetProcAddress(winhttp_handle, "WinHttpGetProxyForUrl"));
730f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (pWHO && pWHCH && pWHGPFU) {
731f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (HINTERNET hWinHttp = pWHO(ToUtf16(agent).c_str(),
732f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                  WINHTTP_ACCESS_TYPE_NO_PROXY,
733f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                  WINHTTP_NO_PROXY_NAME,
734f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                  WINHTTP_NO_PROXY_BYPASS,
735f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                  0)) {
736f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      BOOL result = FALSE;
737f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      WINHTTP_PROXY_INFO info;
738f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      memset(&info, 0, sizeof(info));
739f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (proxy->autodetect) {
740f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Use DHCP and DNS to try to find any proxy to use.
741f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        WINHTTP_AUTOPROXY_OPTIONS options;
742f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        memset(&options, 0, sizeof(options));
743f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        options.fAutoLogonIfChallenged = TRUE;
744f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
745f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        options.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT;
746f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        options.dwAutoDetectFlags |= WINHTTP_AUTO_DETECT_TYPE_DHCP
747f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
748f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        result = MyWinHttpGetProxyForUrl(
749f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            pWHGPFU, hWinHttp, ToUtf16(url).c_str(), &options, &info);
750f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
751f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (!result && !proxy->autoconfig_url.empty()) {
752f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // We have the location of a proxy config file. Download it and
753f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // execute it to find proxy settings for our url.
754f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        WINHTTP_AUTOPROXY_OPTIONS options;
755f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        memset(&options, 0, sizeof(options));
756f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        memset(&info, 0, sizeof(info));
757f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        options.fAutoLogonIfChallenged = TRUE;
758f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
759f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        std::wstring autoconfig_url16((ToUtf16)(proxy->autoconfig_url));
760f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
761f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        options.lpszAutoConfigUrl = autoconfig_url16.c_str();
762f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
763f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        result = MyWinHttpGetProxyForUrl(
764f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            pWHGPFU, hWinHttp, ToUtf16(url).c_str(), &options, &info);
765f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
766f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (result) {
767f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // Either the given auto config url was valid or auto
768f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // detection found a proxy on this network.
769f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (info.lpszProxy) {
770731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          // TODO: Does this bypass list differ from the list
771f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // retreived from GetWinHttpProxySettings earlier?
772f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          if (info.lpszProxyBypass) {
773f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            proxy->bypass_list = ToUtf8(info.lpszProxyBypass);
774f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            GlobalFree(info.lpszProxyBypass);
775f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          } else {
776f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            proxy->bypass_list.clear();
777f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
778f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          if (!ProxyListMatch(purl, proxy->bypass_list, ';')) {
779f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            // Found proxy for this URL. If parsing the address turns
780f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            // out ok then we are successful.
781f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            success = ParseProxy(ToUtf8(info.lpszProxy), proxy);
782f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
783f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          GlobalFree(info.lpszProxy);
784f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
785f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
786f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // We could not find any proxy for this url.
787f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(LS_INFO) << "No proxy detected for " << url;
788f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
789f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      pWHCH(hWinHttp);
790f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
791f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
792f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "Failed loading WinHTTP functions.";
793f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = false;
794f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
795f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  FreeLibrary(winhttp_handle);
796f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
797f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
798f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
799f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if 0  // Below functions currently not used.
800f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
801f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetJsProxySettings(const char* url, ProxyInfo* proxy) {
802f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Url<char> purl(url);
803f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = false;
804f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
805f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (HMODULE hModJS = LoadLibrary(_T("jsproxy.dll"))) {
806f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    pfnInternetGetProxyInfo pIGPI =
807f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        reinterpret_cast<pfnInternetGetProxyInfo>(
808f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            GetProcAddress(hModJS, "InternetGetProxyInfo"));
809f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (pIGPI) {
810f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      char proxy[256], host[256];
811f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      memset(proxy, 0, sizeof(proxy));
812f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      char * ptr = proxy;
813f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      DWORD proxylen = sizeof(proxy);
814f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      std::string surl = Utf8String(url);
815f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      DWORD hostlen = _snprintf(host, sizeof(host), "http%s://%S",
816f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                purl.secure() ? "s" : "", purl.server());
817f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (pIGPI(surl.data(), surl.size(), host, hostlen, &ptr, &proxylen)) {
818f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(INFO) << "Proxy: " << proxy;
819f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
820f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG_GLE(INFO) << "InternetGetProxyInfo";
821f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
822f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
823f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    FreeLibrary(hModJS);
824f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
825f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
826f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
827f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
828f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetWmProxySettings(const char* url, ProxyInfo* proxy) {
829f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Url<char> purl(url);
830f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = false;
831f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
832f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  INSNetSourceCreator * nsc = 0;
833f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  HRESULT hr = CoCreateInstance(CLSID_ClientNetManager, 0, CLSCTX_ALL,
834f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                IID_INSNetSourceCreator, (LPVOID *) &nsc);
835f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (SUCCEEDED(hr)) {
836f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (SUCCEEDED(hr = nsc->Initialize())) {
837f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      VARIANT dispatch;
838f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      VariantInit(&dispatch);
839f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (SUCCEEDED(hr = nsc->GetNetSourceAdminInterface(L"http", &dispatch))) {
840f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        IWMSInternalAdminNetSource * ians = 0;
841f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (SUCCEEDED(hr = dispatch.pdispVal->QueryInterface(
842f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                IID_IWMSInternalAdminNetSource, (LPVOID *) &ians))) {
843f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          _bstr_t host(purl.server());
844f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          BSTR proxy = 0;
845f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          BOOL bProxyEnabled = FALSE;
846f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          DWORD port, context = 0;
847f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          if (SUCCEEDED(hr = ians->FindProxyForURL(
848f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                  L"http", host, &bProxyEnabled, &proxy, &port, &context))) {
849f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            success = true;
850f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            if (bProxyEnabled) {
851f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              _bstr_t sproxy = proxy;
852f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              proxy->ptype = PT_HTTPS;
853f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              proxy->host = sproxy;
854f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch              proxy->port = port;
855f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            }
856f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
857f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          SysFreeString(proxy);
858f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          if (FAILED(hr = ians->ShutdownProxyContext(context))) {
859f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            LOG(LS_INFO) << "IWMSInternalAdminNetSource::ShutdownProxyContext"
860f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                         << "failed: " << hr;
861f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
862f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ians->Release();
863f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
864f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
865f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      VariantClear(&dispatch);
866f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (FAILED(hr = nsc->Shutdown())) {
867f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(LS_INFO) << "INSNetSourceCreator::Shutdown failed: " << hr;
868f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
869f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
870f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    nsc->Release();
871f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
872f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
873f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
874f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
875f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetIePerConnectionProxySettings(const char* url, ProxyInfo* proxy) {
876f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Url<char> purl(url);
877f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = false;
878f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
879f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  INTERNET_PER_CONN_OPTION_LIST list;
880f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  INTERNET_PER_CONN_OPTION options[3];
881f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  memset(&list, 0, sizeof(list));
882f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  memset(&options, 0, sizeof(options));
883f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
884f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  list.dwSize = sizeof(list);
885f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  list.dwOptionCount = 3;
886f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  list.pOptions = options;
887f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  options[0].dwOption = INTERNET_PER_CONN_FLAGS;
888f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  options[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
889f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  options[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
890f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD dwSize = sizeof(list);
891f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
892f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!InternetQueryOption(0, INTERNET_OPTION_PER_CONNECTION_OPTION, &list,
893f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           &dwSize)) {
894f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
895f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if ((options[0].Value.dwValue & PROXY_TYPE_PROXY) != 0) {
896f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = true;
897f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!ProxyListMatch(purl, nonnull(options[2].Value.pszValue), _T(';'))) {
898f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ParseProxy(nonnull(options[1].Value.pszValue), proxy);
899f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
900f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if ((options[0].Value.dwValue & PROXY_TYPE_DIRECT) != 0) {
901f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = true;
902f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
903f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "unknown internet access type: "
904f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                 << options[0].Value.dwValue;
905f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
906f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (options[1].Value.pszValue) {
907f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    GlobalFree(options[1].Value.pszValue);
908f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
909f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (options[2].Value.pszValue) {
910f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    GlobalFree(options[2].Value.pszValue);
911f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
912f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
913f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
914f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
915f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // 0
916f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
917f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Uses the InternetQueryOption function to retrieve proxy settings
918f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// from the registry. This will only give us the 'static' settings,
919f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// ie, not any information about auto config etc.
920f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetIeLanProxySettings(const char* url, ProxyInfo* proxy) {
921f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Url<char> purl(url);
922f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = false;
923f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
924f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  wchar_t buffer[1024];
925f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  memset(buffer, 0, sizeof(buffer));
926f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  INTERNET_PROXY_INFO * info = reinterpret_cast<INTERNET_PROXY_INFO *>(buffer);
927f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD dwSize = sizeof(buffer);
928f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
929f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!InternetQueryOption(0, INTERNET_OPTION_PROXY, info, &dwSize)) {
930f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
931f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (info->dwAccessType == INTERNET_OPEN_TYPE_DIRECT) {
932f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = true;
933f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (info->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
934f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    success = true;
935f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!ProxyListMatch(purl, nonnull(reinterpret_cast<const char*>(
936f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            info->lpszProxyBypass)), ' ')) {
937f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ParseProxy(nonnull(reinterpret_cast<const char*>(info->lpszProxy)),
938f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                 proxy);
939f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
940f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
941f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "unknown internet access type: " << info->dwAccessType;
942f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
943f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
944f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
945f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
946f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetIeProxySettings(const char* agent, const char* url, ProxyInfo* proxy) {
947f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = GetWinHttpProxySettings(url, proxy);
948f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!success) {
949731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // TODO: Should always call this if no proxy were detected by
950f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // GetWinHttpProxySettings?
951f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // WinHttp failed. Try using the InternetOptionQuery method instead.
952f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return GetIeLanProxySettings(url, proxy);
953f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
954f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
955f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
956f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
957f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
958f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
959f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef OSX  // OSX specific implementation for reading system wide
960f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            // proxy settings.
961f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
962f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool p_getProxyInfoForTypeFromDictWithKeys(ProxyInfo* proxy,
963f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           ProxyType type,
964f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           const CFDictionaryRef proxyDict,
965f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           const CFStringRef enabledKey,
966f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           const CFStringRef hostKey,
967f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                           const CFStringRef portKey) {
968f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // whether or not we set up the proxy info.
969f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool result = false;
970f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
971f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // we use this as a scratch variable for determining if operations
972f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // succeeded.
973f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool converted = false;
974f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
975f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // the data we need to construct the SocketAddress for the proxy.
976f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string hostname;
977f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int port;
978f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
979f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if ((proxyDict != NULL) &&
980f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      (CFGetTypeID(proxyDict) == CFDictionaryGetTypeID())) {
981f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // CoreFoundation stuff that we'll have to get from
982f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // the dictionaries and interpret or convert into more usable formats.
983f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    CFNumberRef enabledCFNum;
984f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    CFNumberRef portCFNum;
985f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    CFStringRef hostCFStr;
986f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
987f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    enabledCFNum = (CFNumberRef)CFDictionaryGetValue(proxyDict, enabledKey);
988f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
989f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (p_isCFNumberTrue(enabledCFNum)) {
990f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // let's see if we can get the address and port.
991f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      hostCFStr = (CFStringRef)CFDictionaryGetValue(proxyDict, hostKey);
992f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      converted = p_convertHostCFStringRefToCPPString(hostCFStr, hostname);
993f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (converted) {
994f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        portCFNum = (CFNumberRef)CFDictionaryGetValue(proxyDict, portKey);
995f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        converted = p_convertCFNumberToInt(portCFNum, &port);
996f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (converted) {
997f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // we have something enabled, with a hostname and a port.
998f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // That's sufficient to set up the proxy info.
999f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->type = type;
1000f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetIP(hostname);
1001f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy->address.SetPort(port);
1002f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          result = true;
1003f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1004f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1005f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1006f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1007f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1008f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result;
1009f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1010f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1011f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Looks for proxy information in the given dictionary,
1012f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// return true if it found sufficient information to define one,
1013f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// false otherwise.  This is guaranteed to not change the values in proxy
1014f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// unless a full-fledged proxy description was discovered in the dictionary.
1015f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// However, at the present time this does not support username or password.
1016f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Checks first for a SOCKS proxy, then for HTTPS, then HTTP.
1017f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetMacProxySettingsFromDictionary(ProxyInfo* proxy,
1018f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                       const CFDictionaryRef proxyDict) {
1019f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // the function result.
1020f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool gotProxy = false;
1021f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1022f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1023f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // first we see if there's a SOCKS proxy in place.
1024f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  gotProxy = p_getProxyInfoForTypeFromDictWithKeys(proxy,
1025f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                   PROXY_SOCKS5,
1026f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                   proxyDict,
1027f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                   kSCPropNetProxiesSOCKSEnable,
1028f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                   kSCPropNetProxiesSOCKSProxy,
1029f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                   kSCPropNetProxiesSOCKSPort);
1030f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1031f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!gotProxy) {
1032f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // okay, no SOCKS proxy, let's look for https.
1033f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    gotProxy = p_getProxyInfoForTypeFromDictWithKeys(proxy,
1034f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                               PROXY_HTTPS,
1035f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                               proxyDict,
1036f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                               kSCPropNetProxiesHTTPSEnable,
1037f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                               kSCPropNetProxiesHTTPSProxy,
1038f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                               kSCPropNetProxiesHTTPSPort);
1039f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!gotProxy) {
1040f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Finally, try HTTP proxy. Note that flute doesn't
1041f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // differentiate between HTTPS and HTTP, hence we are using the
1042f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // same flute type here, ie. PROXY_HTTPS.
1043f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      gotProxy = p_getProxyInfoForTypeFromDictWithKeys(
1044f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          proxy, PROXY_HTTPS, proxyDict, kSCPropNetProxiesHTTPEnable,
1045f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort);
1046f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1047f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1048f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return gotProxy;
1049f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1050f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1051f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool p_putPasswordInProxyInfo(ProxyInfo* proxy) {
1052f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool result = true;  // by default we assume we're good.
1053f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // for all we know there isn't any password.  We'll set to false
1054f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // if we find a problem.
1055f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1056f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Ask the keychain for an internet password search for the given protocol.
1057f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  OSStatus oss = 0;
1058f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SecKeychainAttributeList attrList;
1059f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attrList.count = 3;
1060f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SecKeychainAttribute attributes[3];
1061f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attrList.attr = attributes;
1062f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1063f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[0].tag = kSecProtocolItemAttr;
1064f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[0].length = sizeof(SecProtocolType);
1065f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SecProtocolType protocol;
1066f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (proxy->type) {
1067f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case PROXY_HTTPS :
1068f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      protocol = kSecProtocolTypeHTTPS;
1069f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1070f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case PROXY_SOCKS5 :
1071f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      protocol = kSecProtocolTypeSOCKS;
1072f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1073f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default :
1074f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_ERROR) << "asked for proxy password for unknown proxy type.";
1075f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result = false;
1076f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1077f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1078f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[0].data = &protocol;
1079f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1080f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UInt32 port = proxy->address.port();
1081f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[1].tag = kSecPortItemAttr;
1082f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[1].length = sizeof(UInt32);
1083f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[1].data = &port;
1084f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1085f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string ip = proxy->address.IPAsString();
1086f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[2].tag = kSecServerItemAttr;
1087f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[2].length = ip.length();
1088f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  attributes[2].data = const_cast<char*>(ip.c_str());
1089f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1090f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result) {
1091f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "trying to get proxy username/password";
1092f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SecKeychainSearchRef sref;
1093f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    oss = SecKeychainSearchCreateFromAttributes(NULL,
1094f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                kSecInternetPasswordItemClass,
1095f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                &attrList, &sref);
1096f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (0 == oss) {
1097f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_INFO) << "SecKeychainSearchCreateFromAttributes was good";
1098f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Get the first item, if there is one.
1099f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SecKeychainItemRef iref;
1100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      oss = SecKeychainSearchCopyNext(sref, &iref);
1101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (0 == oss) {
1102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(LS_INFO) << "...looks like we have the username/password data";
1103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // If there is, get the username and the password.
1104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        SecKeychainAttributeInfo attribsToGet;
1106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        attribsToGet.count = 1;
1107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        UInt32 tag = kSecAccountItemAttr;
1108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        UInt32 format = CSSM_DB_ATTRIBUTE_FORMAT_STRING;
1109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        void *data;
1110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        UInt32 length;
1111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        SecKeychainAttributeList *localList;
1112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        attribsToGet.tag = &tag;
1114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        attribsToGet.format = &format;
1115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        OSStatus copyres = SecKeychainItemCopyAttributesAndData(iref,
1116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                                &attribsToGet,
1117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                                NULL,
1118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                                &localList,
1119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                                &length,
1120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                                                &data);
1121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (0 == copyres) {
1122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          LOG(LS_INFO) << "...and we can pull it out.";
1123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // now, we know from experimentation (sadly not from docs)
1124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // that the username is in the local attribute list,
1125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // and the password in the data,
1126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // both without null termination but with info on their length.
1127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // grab the password from the data.
1128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          std::string password;
1129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          password.append(static_cast<const char*>(data), length);
1130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // make the password into a CryptString
1132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // huh, at the time of writing, you can't.
1133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // so we'll skip that for now and come back to it later.
1134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          // now put the username in the proxy.
1136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          if (1 <= localList->attr->length) {
1137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            proxy->username.append(
1138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                static_cast<const char*>(localList->attr->data),
1139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                localList->attr->length);
1140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            LOG(LS_INFO) << "username is " << proxy->username;
1141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          } else {
1142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            LOG(LS_ERROR) << "got keychain entry with no username";
1143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch            result = false;
1144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          }
1145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else {
1146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          LOG(LS_ERROR) << "couldn't copy info from keychain.";
1147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          result = false;
1148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
1149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        SecKeychainItemFreeAttributesAndData(localList, data);
1150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else if (errSecItemNotFound == oss) {
1151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(LS_INFO) << "...username/password info not found";
1152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
1153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // oooh, neither 0 nor itemNotFound.
1154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        LOG(LS_ERROR) << "Couldn't get keychain information, error code" << oss;
1155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        result = false;
1156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (errSecItemNotFound == oss) {  // noop
1158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
1159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // oooh, neither 0 nor itemNotFound.
1160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_ERROR) << "Couldn't get keychain information, error code" << oss;
1161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result = false;
1162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result;
1166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetMacProxySettings(ProxyInfo* proxy) {
1169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // based on the Apple Technical Q&A QA1234
1170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // http://developer.apple.com/qa/qa2001/qa1234.html
1171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CFDictionaryRef proxyDict = SCDynamicStoreCopyProxies(NULL);
1172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool result = false;
1173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (proxyDict != NULL) {
1175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // sending it off to another function makes it easier to unit test
1176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // since we can make our own dictionary to hand to that function.
1177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    result = GetMacProxySettingsFromDictionary(proxy, proxyDict);
1178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (result) {
1180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result = p_putPasswordInProxyInfo(proxy);
1181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // We created the dictionary with something that had the
1184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // word 'copy' in it, so we have to release it, according
1185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // to the Carbon memory management standards.
1186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    CFRelease(proxyDict);
1187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
1188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "SCDynamicStoreCopyProxies failed";
1189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result;
1192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // OSX
1194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool AutoDetectProxySettings(const char* agent, const char* url,
1196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                             ProxyInfo* proxy) {
1197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
1198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return WinHttpAutoDetectProxyForUrl(agent, url, proxy);
1199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
1200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_WARNING) << "Proxy auto-detection not implemented for this platform";
1201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return false;
1202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetSystemDefaultProxySettings(const char* agent, const char* url,
1206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                   ProxyInfo* proxy) {
1207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
1208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return GetIeProxySettings(agent, url, proxy);
1209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif OSX
1210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return GetMacProxySettings(proxy);
1211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
1212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO: Get System settings if browser is not firefox.
1213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return GetFirefoxProxySettings(url, proxy);
1214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
1215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool GetProxySettingsForUrl(const char* agent, const char* url,
1218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                            ProxyInfo& proxy, bool long_operation) {
1219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UserAgent a = GetAgent(agent);
1220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool result;
1221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (a) {
1222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case UA_FIREFOX: {
1223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result = GetFirefoxProxySettings(url, &proxy);
1224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32
1227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case UA_INTERNETEXPLORER:
1228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result = GetIeProxySettings(agent, url, &proxy);
1229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case UA_UNKNOWN:
1231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Agent not defined, check default browser.
1232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (IsDefaultBrowserFirefox()) {
1233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        result = GetFirefoxProxySettings(url, &proxy);
1234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
1235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        result = GetIeProxySettings(agent, url, &proxy);
1236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
1237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // WIN32
1239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default:
1240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result = GetSystemDefaultProxySettings(agent, url, &proxy);
1241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO: Consider using the 'long_operation' parameter to
1245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // decide whether to do the auto detection.
1246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result && (proxy.autodetect ||
1247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                 !proxy.autoconfig_url.empty())) {
1248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Use WinHTTP to auto detect proxy for us.
1249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    result = AutoDetectProxySettings(agent, url, &proxy);
1250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!result) {
1251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // Either auto detection is not supported or we simply didn't
1252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // find any proxy, reset type.
1253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      proxy.type = talk_base::PROXY_NONE;
1254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result;
1257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // namespace talk_base
1260