| Index: webrtc/base/proxydetect.cc
|
| diff --git a/webrtc/base/proxydetect.cc b/webrtc/base/proxydetect.cc
|
| deleted file mode 100644
|
| index b0fa30488a1eed3f770bf78afe6fe242b50447a5..0000000000000000000000000000000000000000
|
| --- a/webrtc/base/proxydetect.cc
|
| +++ /dev/null
|
| @@ -1,1292 +0,0 @@
|
| -/*
|
| - * Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#include "webrtc/base/proxydetect.h"
|
| -
|
| -#if defined(WEBRTC_WIN)
|
| -#include "webrtc/base/win32.h"
|
| -#include <shlobj.h>
|
| -#endif // WEBRTC_WIN
|
| -
|
| -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
| -#include <SystemConfiguration/SystemConfiguration.h>
|
| -#include <CoreFoundation/CoreFoundation.h>
|
| -#include <CoreServices/CoreServices.h>
|
| -#include <Security/Security.h>
|
| -#include "macconversion.h"
|
| -#include "webrtc/base/unixfilesystem.h"
|
| -#endif
|
| -
|
| -#ifdef WEBRTC_IOS
|
| -#include <CFNetwork/CFNetwork.h>
|
| -#include "macconversion.h"
|
| -#endif
|
| -
|
| -#include <map>
|
| -#include <memory>
|
| -
|
| -#include "webrtc/base/arraysize.h"
|
| -#include "webrtc/base/checks.h"
|
| -#include "webrtc/base/common.h"
|
| -#include "webrtc/base/fileutils.h"
|
| -#include "webrtc/base/httpcommon.h"
|
| -#include "webrtc/base/httpcommon-inl.h"
|
| -#include "webrtc/base/pathutils.h"
|
| -#include "webrtc/base/stringutils.h"
|
| -
|
| -#define _TRY_JSPROXY 0
|
| -#define _TRY_WM_FINDPROXY 0
|
| -
|
| -#if defined(WEBRTC_WIN)
|
| -#define _TRY_WINHTTP 1
|
| -#define _TRY_IE_LAN_SETTINGS 1
|
| -#else
|
| -#define _TRY_WINHTTP 0
|
| -#define _TRY_IE_LAN_SETTINGS 0
|
| -#endif // WEBRTC_WIN
|
| -
|
| -// For all platforms try Firefox.
|
| -#define _TRY_FIREFOX 1
|
| -
|
| -// Use profiles.ini to find the correct profile for this user.
|
| -// If not set, we'll just look for the default one.
|
| -#define USE_FIREFOX_PROFILES_INI 1
|
| -
|
| -static const size_t kMaxLineLength = 1024;
|
| -static const char kFirefoxPattern[] = "Firefox";
|
| -static const char kInternetExplorerPattern[] = "MSIE";
|
| -
|
| -struct StringMap {
|
| - public:
|
| - void Add(const char * name, const char * value) { map_[name] = value; }
|
| - const std::string& Get(const char * name, const char * def = "") const {
|
| - std::map<std::string, std::string>::const_iterator it =
|
| - map_.find(name);
|
| - if (it != map_.end())
|
| - return it->second;
|
| - def_ = def;
|
| - return def_;
|
| - }
|
| - bool IsSet(const char * name) const {
|
| - return (map_.find(name) != map_.end());
|
| - }
|
| - private:
|
| - std::map<std::string, std::string> map_;
|
| - mutable std::string def_;
|
| -};
|
| -
|
| -enum UserAgent {
|
| - UA_FIREFOX,
|
| - UA_INTERNETEXPLORER,
|
| - UA_OTHER,
|
| - UA_UNKNOWN
|
| -};
|
| -
|
| -#if _TRY_WINHTTP
|
| -//#include <winhttp.h>
|
| -// Note: From winhttp.h
|
| -
|
| -const char WINHTTP[] = "winhttp";
|
| -
|
| -typedef LPVOID HINTERNET;
|
| -
|
| -typedef struct {
|
| - DWORD dwAccessType; // see WINHTTP_ACCESS_* types below
|
| - LPWSTR lpszProxy; // proxy server list
|
| - LPWSTR lpszProxyBypass; // proxy bypass list
|
| -} WINHTTP_PROXY_INFO, * LPWINHTTP_PROXY_INFO;
|
| -
|
| -typedef struct {
|
| - DWORD dwFlags;
|
| - DWORD dwAutoDetectFlags;
|
| - LPCWSTR lpszAutoConfigUrl;
|
| - LPVOID lpvReserved;
|
| - DWORD dwReserved;
|
| - BOOL fAutoLogonIfChallenged;
|
| -} WINHTTP_AUTOPROXY_OPTIONS;
|
| -
|
| -typedef struct {
|
| - BOOL fAutoDetect;
|
| - LPWSTR lpszAutoConfigUrl;
|
| - LPWSTR lpszProxy;
|
| - LPWSTR lpszProxyBypass;
|
| -} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
|
| -
|
| -extern "C" {
|
| - typedef HINTERNET (WINAPI * pfnWinHttpOpen)
|
| - (
|
| - IN LPCWSTR pwszUserAgent,
|
| - IN DWORD dwAccessType,
|
| - IN LPCWSTR pwszProxyName OPTIONAL,
|
| - IN LPCWSTR pwszProxyBypass OPTIONAL,
|
| - IN DWORD dwFlags
|
| - );
|
| - typedef BOOL (STDAPICALLTYPE * pfnWinHttpCloseHandle)
|
| - (
|
| - IN HINTERNET hInternet
|
| - );
|
| - typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetProxyForUrl)
|
| - (
|
| - IN HINTERNET hSession,
|
| - IN LPCWSTR lpcwszUrl,
|
| - IN WINHTTP_AUTOPROXY_OPTIONS * pAutoProxyOptions,
|
| - OUT WINHTTP_PROXY_INFO * pProxyInfo
|
| - );
|
| - typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetIEProxyConfig)
|
| - (
|
| - IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig
|
| - );
|
| -
|
| -} // extern "C"
|
| -
|
| -#define WINHTTP_AUTOPROXY_AUTO_DETECT 0x00000001
|
| -#define WINHTTP_AUTOPROXY_CONFIG_URL 0x00000002
|
| -#define WINHTTP_AUTOPROXY_RUN_INPROCESS 0x00010000
|
| -#define WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY 0x00020000
|
| -#define WINHTTP_AUTO_DETECT_TYPE_DHCP 0x00000001
|
| -#define WINHTTP_AUTO_DETECT_TYPE_DNS_A 0x00000002
|
| -#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY 0
|
| -#define WINHTTP_ACCESS_TYPE_NO_PROXY 1
|
| -#define WINHTTP_ACCESS_TYPE_NAMED_PROXY 3
|
| -#define WINHTTP_NO_PROXY_NAME NULL
|
| -#define WINHTTP_NO_PROXY_BYPASS NULL
|
| -
|
| -#endif // _TRY_WINHTTP
|
| -
|
| -#if _TRY_JSPROXY
|
| -extern "C" {
|
| - typedef BOOL (STDAPICALLTYPE * pfnInternetGetProxyInfo)
|
| - (
|
| - LPCSTR lpszUrl,
|
| - DWORD dwUrlLength,
|
| - LPSTR lpszUrlHostName,
|
| - DWORD dwUrlHostNameLength,
|
| - LPSTR * lplpszProxyHostName,
|
| - LPDWORD lpdwProxyHostNameLength
|
| - );
|
| -} // extern "C"
|
| -#endif // _TRY_JSPROXY
|
| -
|
| -#if _TRY_WM_FINDPROXY
|
| -#include <comutil.h>
|
| -#include <wmnetsourcecreator.h>
|
| -#include <wmsinternaladminnetsource.h>
|
| -#endif // _TRY_WM_FINDPROXY
|
| -
|
| -#if _TRY_IE_LAN_SETTINGS
|
| -#include <wininet.h>
|
| -#include <string>
|
| -#endif // _TRY_IE_LAN_SETTINGS
|
| -
|
| -namespace rtc {
|
| -
|
| -//////////////////////////////////////////////////////////////////////
|
| -// Utility Functions
|
| -//////////////////////////////////////////////////////////////////////
|
| -
|
| -#if defined(WEBRTC_WIN)
|
| -#ifdef _UNICODE
|
| -
|
| -typedef std::wstring tstring;
|
| -std::string Utf8String(const tstring& str) { return ToUtf8(str); }
|
| -
|
| -#else // !_UNICODE
|
| -
|
| -typedef std::string tstring;
|
| -std::string Utf8String(const tstring& str) { return str; }
|
| -
|
| -#endif // !_UNICODE
|
| -#endif // WEBRTC_WIN
|
| -
|
| -bool ProxyItemMatch(const Url<char>& url, char * item, size_t len) {
|
| - // hostname:443
|
| - if (char * port = ::strchr(item, ':')) {
|
| - *port++ = '\0';
|
| - if (url.port() != atol(port)) {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - // A.B.C.D or A.B.C.D/24
|
| - int a, b, c, d, m;
|
| - int match = sscanf(item, "%d.%d.%d.%d/%d", &a, &b, &c, &d, &m);
|
| - if (match >= 4) {
|
| - uint32_t ip = ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) |
|
| - (d & 0xFF);
|
| - if ((match < 5) || (m > 32))
|
| - m = 32;
|
| - else if (m < 0)
|
| - m = 0;
|
| - uint32_t mask = (m == 0) ? 0 : (~0UL) << (32 - m);
|
| - SocketAddress addr(url.host(), 0);
|
| - // TODO: Support IPv6 proxyitems. This code block is IPv4 only anyway.
|
| - return !addr.IsUnresolvedIP() &&
|
| - ((addr.ipaddr().v4AddressAsHostOrderInteger() & mask) == (ip & mask));
|
| - }
|
| -
|
| - // .foo.com
|
| - if (*item == '.') {
|
| - size_t hostlen = url.host().length();
|
| - return (hostlen > len)
|
| - && (stricmp(url.host().c_str() + (hostlen - len), item) == 0);
|
| - }
|
| -
|
| - // localhost or www.*.com
|
| - if (!string_match(url.host().c_str(), item))
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ProxyListMatch(const Url<char>& url, const std::string& proxy_list,
|
| - char sep) {
|
| - const size_t BUFSIZE = 256;
|
| - char buffer[BUFSIZE];
|
| - const char* list = proxy_list.c_str();
|
| - while (*list) {
|
| - // Remove leading space
|
| - if (isspace(*list)) {
|
| - ++list;
|
| - continue;
|
| - }
|
| - // Break on separator
|
| - size_t len;
|
| - const char * start = list;
|
| - if (const char * end = ::strchr(list, sep)) {
|
| - len = (end - list);
|
| - list += len + 1;
|
| - } else {
|
| - len = strlen(list);
|
| - list += len;
|
| - }
|
| - // Remove trailing space
|
| - while ((len > 0) && isspace(start[len-1]))
|
| - --len;
|
| - // Check for oversized entry
|
| - if (len >= BUFSIZE)
|
| - continue;
|
| - memcpy(buffer, start, len);
|
| - buffer[len] = 0;
|
| - if (!ProxyItemMatch(url, buffer, len))
|
| - continue;
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool Better(ProxyType lhs, const ProxyType rhs) {
|
| - // PROXY_NONE, PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN
|
| - const int PROXY_VALUE[5] = { 0, 2, 3, 1 };
|
| - return (PROXY_VALUE[lhs] > PROXY_VALUE[rhs]);
|
| -}
|
| -
|
| -bool ParseProxy(const std::string& saddress, ProxyInfo* proxy) {
|
| - const size_t kMaxAddressLength = 1024;
|
| - // Allow semicolon, space, or tab as an address separator
|
| - const char* const kAddressSeparator = " ;\t";
|
| -
|
| - ProxyType ptype;
|
| - std::string host;
|
| - uint16_t port;
|
| -
|
| - const char* address = saddress.c_str();
|
| - while (*address) {
|
| - size_t len;
|
| - const char * start = address;
|
| - if (const char * sep = strchr(address, kAddressSeparator)) {
|
| - len = (sep - address);
|
| - address += len + 1;
|
| - while (*address != '\0' && ::strchr(kAddressSeparator, *address)) {
|
| - address += 1;
|
| - }
|
| - } else {
|
| - len = strlen(address);
|
| - address += len;
|
| - }
|
| -
|
| - if (len > kMaxAddressLength - 1) {
|
| - LOG(LS_WARNING) << "Proxy address too long [" << start << "]";
|
| - continue;
|
| - }
|
| -
|
| - char buffer[kMaxAddressLength];
|
| - memcpy(buffer, start, len);
|
| - buffer[len] = 0;
|
| -
|
| - char * colon = ::strchr(buffer, ':');
|
| - if (!colon) {
|
| - LOG(LS_WARNING) << "Proxy address without port [" << buffer << "]";
|
| - continue;
|
| - }
|
| -
|
| - *colon = 0;
|
| - char * endptr;
|
| - port = static_cast<uint16_t>(strtol(colon + 1, &endptr, 0));
|
| - if (*endptr != 0) {
|
| - LOG(LS_WARNING) << "Proxy address with invalid port [" << buffer << "]";
|
| - continue;
|
| - }
|
| -
|
| - if (char * equals = ::strchr(buffer, '=')) {
|
| - *equals = 0;
|
| - host = equals + 1;
|
| - if (_stricmp(buffer, "socks") == 0) {
|
| - ptype = PROXY_SOCKS5;
|
| - } else if (_stricmp(buffer, "https") == 0) {
|
| - ptype = PROXY_HTTPS;
|
| - } else {
|
| - LOG(LS_WARNING) << "Proxy address with unknown protocol ["
|
| - << buffer << "]";
|
| - ptype = PROXY_UNKNOWN;
|
| - }
|
| - } else {
|
| - host = buffer;
|
| - ptype = PROXY_UNKNOWN;
|
| - }
|
| -
|
| - if (Better(ptype, proxy->type)) {
|
| - proxy->type = ptype;
|
| - proxy->address.SetIP(host);
|
| - proxy->address.SetPort(port);
|
| - }
|
| - }
|
| -
|
| - return proxy->type != PROXY_NONE;
|
| -}
|
| -
|
| -UserAgent GetAgent(const char* agent) {
|
| - if (agent) {
|
| - std::string agent_str(agent);
|
| - if (agent_str.find(kFirefoxPattern) != std::string::npos) {
|
| - return UA_FIREFOX;
|
| - } else if (agent_str.find(kInternetExplorerPattern) != std::string::npos) {
|
| - return UA_INTERNETEXPLORER;
|
| - } else if (agent_str.empty()) {
|
| - return UA_UNKNOWN;
|
| - }
|
| - }
|
| - return UA_OTHER;
|
| -}
|
| -
|
| -bool EndsWith(const std::string& a, const std::string& b) {
|
| - if (b.size() > a.size()) {
|
| - return false;
|
| - }
|
| - int result = a.compare(a.size() - b.size(), b.size(), b);
|
| - return result == 0;
|
| -}
|
| -
|
| -bool GetFirefoxProfilePath(Pathname* path) {
|
| -#if defined(WEBRTC_WIN)
|
| - wchar_t w_path[MAX_PATH];
|
| - if (SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, w_path) !=
|
| - S_OK) {
|
| - LOG(LS_ERROR) << "SHGetFolderPath failed";
|
| - return false;
|
| - }
|
| - path->SetFolder(ToUtf8(w_path, wcslen(w_path)));
|
| - path->AppendFolder("Mozilla");
|
| - path->AppendFolder("Firefox");
|
| -#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
| - rtc::UnixFilesystem filesystem;
|
| - filesystem.SetApplicationName("Firefox");
|
| - bool result = filesystem.GetAppDataFolder(path, true);
|
| - return result;
|
| -#else
|
| - char* user_home = getenv("HOME");
|
| - if (user_home == NULL) {
|
| - return false;
|
| - }
|
| - path->SetFolder(std::string(user_home));
|
| - path->AppendFolder(".mozilla");
|
| - path->AppendFolder("firefox");
|
| -#endif // WEBRTC_WIN
|
| - return true;
|
| -}
|
| -
|
| -bool GetDefaultFirefoxProfile(Pathname* profile_path) {
|
| - RTC_DCHECK(NULL != profile_path);
|
| - Pathname path;
|
| - if (!GetFirefoxProfilePath(&path)) {
|
| - return false;
|
| - }
|
| -
|
| -#if USE_FIREFOX_PROFILES_INI
|
| - // [Profile0]
|
| - // Name=default
|
| - // IsRelative=1
|
| - // Path=Profiles/2de53ejb.default
|
| - // Default=1
|
| -
|
| - // Note: we are looking for the first entry with "Default=1", or the last
|
| - // entry in the file
|
| - path.SetFilename("profiles.ini");
|
| - std::unique_ptr<FileStream> fs(Filesystem::OpenFile(path, "r"));
|
| - if (!fs) {
|
| - return false;
|
| - }
|
| - Pathname candidate;
|
| - bool relative = true;
|
| - std::string line;
|
| - while (fs->ReadLine(&line) == SR_SUCCESS) {
|
| - if (line.length() == 0) {
|
| - continue;
|
| - }
|
| - if (line.at(0) == '[') {
|
| - relative = true;
|
| - candidate.clear();
|
| - } else if (line.find("IsRelative=") == 0 &&
|
| - line.length() >= 12) {
|
| - // TODO: The initial Linux public launch revealed a fairly
|
| - // high number of machines where IsRelative= did not have anything after
|
| - // it. Perhaps that is legal profiles.ini syntax?
|
| - relative = (line.at(11) != '0');
|
| - } else if (line.find("Path=") == 0 &&
|
| - line.length() >= 6) {
|
| - if (relative) {
|
| - candidate = path;
|
| - } else {
|
| - candidate.clear();
|
| - }
|
| - candidate.AppendFolder(line.substr(5));
|
| - } else if (line.find("Default=") == 0 &&
|
| - line.length() >= 9) {
|
| - if ((line.at(8) != '0') && !candidate.empty()) {
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - fs->Close();
|
| - if (candidate.empty()) {
|
| - return false;
|
| - }
|
| - profile_path->SetPathname(candidate.pathname());
|
| -
|
| -#else // !USE_FIREFOX_PROFILES_INI
|
| - path.AppendFolder("Profiles");
|
| - DirectoryIterator* it = Filesystem::IterateDirectory();
|
| - it->Iterate(path);
|
| - std::string extension(".default");
|
| - while (!EndsWith(it->Name(), extension)) {
|
| - if (!it->Next()) {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - profile_path->SetPathname(path);
|
| - profile->AppendFolder("Profiles");
|
| - profile->AppendFolder(it->Name());
|
| - delete it;
|
| -
|
| -#endif // !USE_FIREFOX_PROFILES_INI
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ReadFirefoxPrefs(const Pathname& filename,
|
| - const char * prefix,
|
| - StringMap* settings) {
|
| - std::unique_ptr<FileStream> fs(Filesystem::OpenFile(filename, "r"));
|
| - if (!fs) {
|
| - LOG(LS_ERROR) << "Failed to open file: " << filename.pathname();
|
| - return false;
|
| - }
|
| -
|
| - std::string line;
|
| - while (fs->ReadLine(&line) == SR_SUCCESS) {
|
| - size_t prefix_len = strlen(prefix);
|
| -
|
| - // Skip blank lines and too long lines.
|
| - if ((line.length() == 0) || (line.length() > kMaxLineLength)
|
| - || (line.at(0) == '#') || line.compare(0, 2, "/*") == 0
|
| - || line.compare(0, 2, " *") == 0) {
|
| - continue;
|
| - }
|
| -
|
| - char buffer[kMaxLineLength];
|
| - strcpyn(buffer, sizeof(buffer), line.c_str());
|
| - int nstart = 0, nend = 0, vstart = 0, vend = 0;
|
| - sscanf(buffer, "user_pref(\"%n%*[^\"]%n\", %n%*[^)]%n);",
|
| - &nstart, &nend, &vstart, &vend);
|
| - if (vend > 0) {
|
| - char* name = buffer + nstart;
|
| - name[nend - nstart] = 0;
|
| - if ((vend - vstart >= 2) && (buffer[vstart] == '"')) {
|
| - vstart += 1;
|
| - vend -= 1;
|
| - }
|
| - char* value = buffer + vstart;
|
| - value[vend - vstart] = 0;
|
| - if ((strncmp(name, prefix, prefix_len) == 0) && *value) {
|
| - settings->Add(name + prefix_len, value);
|
| - }
|
| - } else {
|
| - LOG_F(LS_WARNING) << "Unparsed pref [" << buffer << "]";
|
| - }
|
| - }
|
| - fs->Close();
|
| - return true;
|
| -}
|
| -
|
| -bool GetFirefoxProxySettings(const char* url, ProxyInfo* proxy) {
|
| - Url<char> purl(url);
|
| - Pathname path;
|
| - bool success = false;
|
| - if (GetDefaultFirefoxProfile(&path)) {
|
| - StringMap settings;
|
| - path.SetFilename("prefs.js");
|
| - if (ReadFirefoxPrefs(path, "network.proxy.", &settings)) {
|
| - success = true;
|
| - proxy->bypass_list =
|
| - settings.Get("no_proxies_on", "localhost, 127.0.0.1");
|
| - if (settings.Get("type") == "1") {
|
| - // User has manually specified a proxy, try to figure out what
|
| - // type it is.
|
| - if (ProxyListMatch(purl, proxy->bypass_list.c_str(), ',')) {
|
| - // Our url is in the list of url's to bypass proxy.
|
| - } else if (settings.Get("share_proxy_settings") == "true") {
|
| - proxy->type = PROXY_UNKNOWN;
|
| - proxy->address.SetIP(settings.Get("http"));
|
| - proxy->address.SetPort(atoi(settings.Get("http_port").c_str()));
|
| - } else if (settings.IsSet("socks")) {
|
| - proxy->type = PROXY_SOCKS5;
|
| - proxy->address.SetIP(settings.Get("socks"));
|
| - proxy->address.SetPort(atoi(settings.Get("socks_port").c_str()));
|
| - } else if (settings.IsSet("ssl")) {
|
| - proxy->type = PROXY_HTTPS;
|
| - proxy->address.SetIP(settings.Get("ssl"));
|
| - proxy->address.SetPort(atoi(settings.Get("ssl_port").c_str()));
|
| - } else if (settings.IsSet("http")) {
|
| - proxy->type = PROXY_HTTPS;
|
| - proxy->address.SetIP(settings.Get("http"));
|
| - proxy->address.SetPort(atoi(settings.Get("http_port").c_str()));
|
| - }
|
| - } else if (settings.Get("type") == "2") {
|
| - // Browser is configured to get proxy settings from a given url.
|
| - proxy->autoconfig_url = settings.Get("autoconfig_url").c_str();
|
| - } else if (settings.Get("type") == "4") {
|
| - // Browser is configured to auto detect proxy config.
|
| - proxy->autodetect = true;
|
| - } else {
|
| - // No proxy set.
|
| - }
|
| - }
|
| - }
|
| - return success;
|
| -}
|
| -
|
| -#if defined(WEBRTC_WIN) // Windows specific implementation for reading Internet
|
| - // Explorer proxy settings.
|
| -
|
| -void LogGetProxyFault() {
|
| - LOG_GLEM(LERROR, WINHTTP) << "WinHttpGetProxyForUrl faulted!!";
|
| -}
|
| -
|
| -BOOL MyWinHttpGetProxyForUrl(pfnWinHttpGetProxyForUrl pWHGPFU,
|
| - HINTERNET hWinHttp, LPCWSTR url,
|
| - WINHTTP_AUTOPROXY_OPTIONS *options,
|
| - WINHTTP_PROXY_INFO *info) {
|
| - // WinHttpGetProxyForUrl() can call plugins which can crash.
|
| - // In the case of McAfee scriptproxy.dll, it does crash in
|
| - // older versions. Try to catch crashes here and treat as an
|
| - // error.
|
| - BOOL success = FALSE;
|
| -
|
| -#if (_HAS_EXCEPTIONS == 0)
|
| - __try {
|
| - success = pWHGPFU(hWinHttp, url, options, info);
|
| - } __except(EXCEPTION_EXECUTE_HANDLER) {
|
| - // This is a separate function to avoid
|
| - // Visual C++ error 2712 when compiling with C++ EH
|
| - LogGetProxyFault();
|
| - }
|
| -#else
|
| - success = pWHGPFU(hWinHttp, url, options, info);
|
| -#endif // (_HAS_EXCEPTIONS == 0)
|
| -
|
| - return success;
|
| -}
|
| -
|
| -bool IsDefaultBrowserFirefox() {
|
| - HKEY key;
|
| - LONG result = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command",
|
| - 0, KEY_READ, &key);
|
| - if (ERROR_SUCCESS != result)
|
| - return false;
|
| -
|
| - DWORD size, type;
|
| - bool success = false;
|
| - result = RegQueryValueEx(key, L"", 0, &type, NULL, &size);
|
| - if (result == ERROR_SUCCESS && type == REG_SZ) {
|
| - wchar_t* value = new wchar_t[size+1];
|
| - BYTE* buffer = reinterpret_cast<BYTE*>(value);
|
| - result = RegQueryValueEx(key, L"", 0, &type, buffer, &size);
|
| - if (result == ERROR_SUCCESS) {
|
| - // Size returned by RegQueryValueEx is in bytes, convert to number of
|
| - // wchar_t's.
|
| - size /= sizeof(value[0]);
|
| - value[size] = L'\0';
|
| - for (size_t i = 0; i < size; ++i) {
|
| - value[i] = tolowercase(value[i]);
|
| - }
|
| - success = (NULL != strstr(value, L"firefox.exe"));
|
| - }
|
| - delete[] value;
|
| - }
|
| -
|
| - RegCloseKey(key);
|
| - return success;
|
| -}
|
| -
|
| -bool GetWinHttpProxySettings(const char* url, ProxyInfo* proxy) {
|
| - HMODULE winhttp_handle = LoadLibrary(L"winhttp.dll");
|
| - if (winhttp_handle == NULL) {
|
| - LOG(LS_ERROR) << "Failed to load winhttp.dll.";
|
| - return false;
|
| - }
|
| - WINHTTP_CURRENT_USER_IE_PROXY_CONFIG iecfg;
|
| - memset(&iecfg, 0, sizeof(iecfg));
|
| - Url<char> purl(url);
|
| - pfnWinHttpGetIEProxyConfig pWHGIEPC =
|
| - reinterpret_cast<pfnWinHttpGetIEProxyConfig>(
|
| - GetProcAddress(winhttp_handle,
|
| - "WinHttpGetIEProxyConfigForCurrentUser"));
|
| - bool success = false;
|
| - if (pWHGIEPC && pWHGIEPC(&iecfg)) {
|
| - // We were read proxy config successfully.
|
| - success = true;
|
| - if (iecfg.fAutoDetect) {
|
| - proxy->autodetect = true;
|
| - }
|
| - if (iecfg.lpszAutoConfigUrl) {
|
| - proxy->autoconfig_url = ToUtf8(iecfg.lpszAutoConfigUrl);
|
| - GlobalFree(iecfg.lpszAutoConfigUrl);
|
| - }
|
| - if (iecfg.lpszProxyBypass) {
|
| - proxy->bypass_list = ToUtf8(iecfg.lpszProxyBypass);
|
| - GlobalFree(iecfg.lpszProxyBypass);
|
| - }
|
| - if (iecfg.lpszProxy) {
|
| - if (!ProxyListMatch(purl, proxy->bypass_list, ';')) {
|
| - ParseProxy(ToUtf8(iecfg.lpszProxy), proxy);
|
| - }
|
| - GlobalFree(iecfg.lpszProxy);
|
| - }
|
| - }
|
| - FreeLibrary(winhttp_handle);
|
| - return success;
|
| -}
|
| -
|
| -// Uses the WinHTTP API to auto detect proxy for the given url. Firefox and IE
|
| -// have slightly different option dialogs for proxy settings. In Firefox,
|
| -// either a location of a proxy configuration file can be specified or auto
|
| -// detection can be selected. In IE theese two options can be independently
|
| -// selected. For the case where both options are selected (only IE) we try to
|
| -// fetch the config file first, and if that fails we'll perform an auto
|
| -// detection.
|
| -//
|
| -// Returns true if we successfully performed an auto detection not depending on
|
| -// whether we found a proxy or not. Returns false on error.
|
| -bool WinHttpAutoDetectProxyForUrl(const char* agent, const char* url,
|
| - ProxyInfo* proxy) {
|
| - Url<char> purl(url);
|
| - bool success = true;
|
| - HMODULE winhttp_handle = LoadLibrary(L"winhttp.dll");
|
| - if (winhttp_handle == NULL) {
|
| - LOG(LS_ERROR) << "Failed to load winhttp.dll.";
|
| - return false;
|
| - }
|
| - pfnWinHttpOpen pWHO =
|
| - reinterpret_cast<pfnWinHttpOpen>(GetProcAddress(winhttp_handle,
|
| - "WinHttpOpen"));
|
| - pfnWinHttpCloseHandle pWHCH =
|
| - reinterpret_cast<pfnWinHttpCloseHandle>(
|
| - GetProcAddress(winhttp_handle, "WinHttpCloseHandle"));
|
| - pfnWinHttpGetProxyForUrl pWHGPFU =
|
| - reinterpret_cast<pfnWinHttpGetProxyForUrl>(
|
| - GetProcAddress(winhttp_handle, "WinHttpGetProxyForUrl"));
|
| - if (pWHO && pWHCH && pWHGPFU) {
|
| - if (HINTERNET hWinHttp = pWHO(ToUtf16(agent).c_str(),
|
| - WINHTTP_ACCESS_TYPE_NO_PROXY,
|
| - WINHTTP_NO_PROXY_NAME,
|
| - WINHTTP_NO_PROXY_BYPASS,
|
| - 0)) {
|
| - BOOL result = FALSE;
|
| - WINHTTP_PROXY_INFO info;
|
| - memset(&info, 0, sizeof(info));
|
| - if (proxy->autodetect) {
|
| - // Use DHCP and DNS to try to find any proxy to use.
|
| - WINHTTP_AUTOPROXY_OPTIONS options;
|
| - memset(&options, 0, sizeof(options));
|
| - options.fAutoLogonIfChallenged = TRUE;
|
| -
|
| - options.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT;
|
| - options.dwAutoDetectFlags |= WINHTTP_AUTO_DETECT_TYPE_DHCP
|
| - | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
|
| - result = MyWinHttpGetProxyForUrl(
|
| - pWHGPFU, hWinHttp, ToUtf16(url).c_str(), &options, &info);
|
| - }
|
| - if (!result && !proxy->autoconfig_url.empty()) {
|
| - // We have the location of a proxy config file. Download it and
|
| - // execute it to find proxy settings for our url.
|
| - WINHTTP_AUTOPROXY_OPTIONS options;
|
| - memset(&options, 0, sizeof(options));
|
| - memset(&info, 0, sizeof(info));
|
| - options.fAutoLogonIfChallenged = TRUE;
|
| -
|
| - std::wstring autoconfig_url16((ToUtf16)(proxy->autoconfig_url));
|
| - options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
|
| - options.lpszAutoConfigUrl = autoconfig_url16.c_str();
|
| -
|
| - result = MyWinHttpGetProxyForUrl(
|
| - pWHGPFU, hWinHttp, ToUtf16(url).c_str(), &options, &info);
|
| - }
|
| - if (result) {
|
| - // Either the given auto config url was valid or auto
|
| - // detection found a proxy on this network.
|
| - if (info.lpszProxy) {
|
| - // TODO: Does this bypass list differ from the list
|
| - // retreived from GetWinHttpProxySettings earlier?
|
| - if (info.lpszProxyBypass) {
|
| - proxy->bypass_list = ToUtf8(info.lpszProxyBypass);
|
| - GlobalFree(info.lpszProxyBypass);
|
| - } else {
|
| - proxy->bypass_list.clear();
|
| - }
|
| - if (!ProxyListMatch(purl, proxy->bypass_list, ';')) {
|
| - // Found proxy for this URL. If parsing the address turns
|
| - // out ok then we are successful.
|
| - success = ParseProxy(ToUtf8(info.lpszProxy), proxy);
|
| - }
|
| - GlobalFree(info.lpszProxy);
|
| - }
|
| - } else {
|
| - // We could not find any proxy for this url.
|
| - LOG(LS_INFO) << "No proxy detected for " << url;
|
| - }
|
| - pWHCH(hWinHttp);
|
| - }
|
| - } else {
|
| - LOG(LS_ERROR) << "Failed loading WinHTTP functions.";
|
| - success = false;
|
| - }
|
| - FreeLibrary(winhttp_handle);
|
| - return success;
|
| -}
|
| -
|
| -#if 0 // Below functions currently not used.
|
| -
|
| -bool GetJsProxySettings(const char* url, ProxyInfo* proxy) {
|
| - Url<char> purl(url);
|
| - bool success = false;
|
| -
|
| - if (HMODULE hModJS = LoadLibrary(_T("jsproxy.dll"))) {
|
| - pfnInternetGetProxyInfo pIGPI =
|
| - reinterpret_cast<pfnInternetGetProxyInfo>(
|
| - GetProcAddress(hModJS, "InternetGetProxyInfo"));
|
| - if (pIGPI) {
|
| - char proxy[256], host[256];
|
| - memset(proxy, 0, sizeof(proxy));
|
| - char * ptr = proxy;
|
| - DWORD proxylen = sizeof(proxy);
|
| - std::string surl = Utf8String(url);
|
| - DWORD hostlen = _snprintf(host, sizeof(host), "http%s://%S",
|
| - purl.secure() ? "s" : "", purl.server());
|
| - if (pIGPI(surl.data(), surl.size(), host, hostlen, &ptr, &proxylen)) {
|
| - LOG(INFO) << "Proxy: " << proxy;
|
| - } else {
|
| - LOG_GLE(INFO) << "InternetGetProxyInfo";
|
| - }
|
| - }
|
| - FreeLibrary(hModJS);
|
| - }
|
| - return success;
|
| -}
|
| -
|
| -bool GetWmProxySettings(const char* url, ProxyInfo* proxy) {
|
| - Url<char> purl(url);
|
| - bool success = false;
|
| -
|
| - INSNetSourceCreator * nsc = 0;
|
| - HRESULT hr = CoCreateInstance(CLSID_ClientNetManager, 0, CLSCTX_ALL,
|
| - IID_INSNetSourceCreator, (LPVOID *) &nsc);
|
| - if (SUCCEEDED(hr)) {
|
| - if (SUCCEEDED(hr = nsc->Initialize())) {
|
| - VARIANT dispatch;
|
| - VariantInit(&dispatch);
|
| - if (SUCCEEDED(hr = nsc->GetNetSourceAdminInterface(L"http", &dispatch))) {
|
| - IWMSInternalAdminNetSource * ians = 0;
|
| - if (SUCCEEDED(hr = dispatch.pdispVal->QueryInterface(
|
| - IID_IWMSInternalAdminNetSource, (LPVOID *) &ians))) {
|
| - _bstr_t host(purl.server());
|
| - BSTR proxy = 0;
|
| - BOOL bProxyEnabled = FALSE;
|
| - DWORD port, context = 0;
|
| - if (SUCCEEDED(hr = ians->FindProxyForURL(
|
| - L"http", host, &bProxyEnabled, &proxy, &port, &context))) {
|
| - success = true;
|
| - if (bProxyEnabled) {
|
| - _bstr_t sproxy = proxy;
|
| - proxy->ptype = PT_HTTPS;
|
| - proxy->host = sproxy;
|
| - proxy->port = port;
|
| - }
|
| - }
|
| - SysFreeString(proxy);
|
| - if (FAILED(hr = ians->ShutdownProxyContext(context))) {
|
| - LOG(LS_INFO) << "IWMSInternalAdminNetSource::ShutdownProxyContext"
|
| - << "failed: " << hr;
|
| - }
|
| - ians->Release();
|
| - }
|
| - }
|
| - VariantClear(&dispatch);
|
| - if (FAILED(hr = nsc->Shutdown())) {
|
| - LOG(LS_INFO) << "INSNetSourceCreator::Shutdown failed: " << hr;
|
| - }
|
| - }
|
| - nsc->Release();
|
| - }
|
| - return success;
|
| -}
|
| -
|
| -bool GetIePerConnectionProxySettings(const char* url, ProxyInfo* proxy) {
|
| - Url<char> purl(url);
|
| - bool success = false;
|
| -
|
| - INTERNET_PER_CONN_OPTION_LIST list;
|
| - INTERNET_PER_CONN_OPTION options[3];
|
| - memset(&list, 0, sizeof(list));
|
| - memset(&options, 0, sizeof(options));
|
| -
|
| - list.dwSize = sizeof(list);
|
| - list.dwOptionCount = 3;
|
| - list.pOptions = options;
|
| - options[0].dwOption = INTERNET_PER_CONN_FLAGS;
|
| - options[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
|
| - options[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
|
| - DWORD dwSize = sizeof(list);
|
| -
|
| - if (!InternetQueryOption(0, INTERNET_OPTION_PER_CONNECTION_OPTION, &list,
|
| - &dwSize)) {
|
| - LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
|
| - } else if ((options[0].Value.dwValue & PROXY_TYPE_PROXY) != 0) {
|
| - success = true;
|
| - if (!ProxyListMatch(purl, nonnull(options[2].Value.pszValue), _T(';'))) {
|
| - ParseProxy(nonnull(options[1].Value.pszValue), proxy);
|
| - }
|
| - } else if ((options[0].Value.dwValue & PROXY_TYPE_DIRECT) != 0) {
|
| - success = true;
|
| - } else {
|
| - LOG(LS_INFO) << "unknown internet access type: "
|
| - << options[0].Value.dwValue;
|
| - }
|
| - if (options[1].Value.pszValue) {
|
| - GlobalFree(options[1].Value.pszValue);
|
| - }
|
| - if (options[2].Value.pszValue) {
|
| - GlobalFree(options[2].Value.pszValue);
|
| - }
|
| - return success;
|
| -}
|
| -
|
| -#endif // 0
|
| -
|
| -// Uses the InternetQueryOption function to retrieve proxy settings
|
| -// from the registry. This will only give us the 'static' settings,
|
| -// ie, not any information about auto config etc.
|
| -bool GetIeLanProxySettings(const char* url, ProxyInfo* proxy) {
|
| - Url<char> purl(url);
|
| - bool success = false;
|
| -
|
| - wchar_t buffer[1024];
|
| - memset(buffer, 0, sizeof(buffer));
|
| - INTERNET_PROXY_INFO * info = reinterpret_cast<INTERNET_PROXY_INFO *>(buffer);
|
| - DWORD dwSize = sizeof(buffer);
|
| -
|
| - if (!InternetQueryOption(0, INTERNET_OPTION_PROXY, info, &dwSize)) {
|
| - LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
|
| - } else if (info->dwAccessType == INTERNET_OPEN_TYPE_DIRECT) {
|
| - success = true;
|
| - } else if (info->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
|
| - success = true;
|
| - if (!ProxyListMatch(purl, nonnull(reinterpret_cast<const char*>(
|
| - info->lpszProxyBypass)), ' ')) {
|
| - ParseProxy(nonnull(reinterpret_cast<const char*>(info->lpszProxy)),
|
| - proxy);
|
| - }
|
| - } else {
|
| - LOG(LS_INFO) << "unknown internet access type: " << info->dwAccessType;
|
| - }
|
| - return success;
|
| -}
|
| -
|
| -bool GetIeProxySettings(const char* agent, const char* url, ProxyInfo* proxy) {
|
| - bool success = GetWinHttpProxySettings(url, proxy);
|
| - if (!success) {
|
| - // TODO: Should always call this if no proxy were detected by
|
| - // GetWinHttpProxySettings?
|
| - // WinHttp failed. Try using the InternetOptionQuery method instead.
|
| - return GetIeLanProxySettings(url, proxy);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -#endif // WEBRTC_WIN
|
| -
|
| -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) // WEBRTC_MAC && !defined(WEBRTC_IOS) specific implementation for reading system wide
|
| - // proxy settings.
|
| -
|
| -bool p_getProxyInfoForTypeFromDictWithKeys(ProxyInfo* proxy,
|
| - ProxyType type,
|
| - const CFDictionaryRef proxyDict,
|
| - const CFStringRef enabledKey,
|
| - const CFStringRef hostKey,
|
| - const CFStringRef portKey) {
|
| - // whether or not we set up the proxy info.
|
| - bool result = false;
|
| -
|
| - // we use this as a scratch variable for determining if operations
|
| - // succeeded.
|
| - bool converted = false;
|
| -
|
| - // the data we need to construct the SocketAddress for the proxy.
|
| - std::string hostname;
|
| - int port;
|
| -
|
| - if ((proxyDict != NULL) &&
|
| - (CFGetTypeID(proxyDict) == CFDictionaryGetTypeID())) {
|
| - // CoreFoundation stuff that we'll have to get from
|
| - // the dictionaries and interpret or convert into more usable formats.
|
| - CFNumberRef enabledCFNum;
|
| - CFNumberRef portCFNum;
|
| - CFStringRef hostCFStr;
|
| -
|
| - enabledCFNum = (CFNumberRef)CFDictionaryGetValue(proxyDict, enabledKey);
|
| -
|
| - if (p_isCFNumberTrue(enabledCFNum)) {
|
| - // let's see if we can get the address and port.
|
| - hostCFStr = (CFStringRef)CFDictionaryGetValue(proxyDict, hostKey);
|
| - converted = p_convertHostCFStringRefToCPPString(hostCFStr, hostname);
|
| - if (converted) {
|
| - portCFNum = (CFNumberRef)CFDictionaryGetValue(proxyDict, portKey);
|
| - converted = p_convertCFNumberToInt(portCFNum, &port);
|
| - if (converted) {
|
| - // we have something enabled, with a hostname and a port.
|
| - // That's sufficient to set up the proxy info.
|
| - proxy->type = type;
|
| - proxy->address.SetIP(hostname);
|
| - proxy->address.SetPort(port);
|
| - result = true;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -
|
| -// Looks for proxy information in the given dictionary,
|
| -// return true if it found sufficient information to define one,
|
| -// false otherwise. This is guaranteed to not change the values in proxy
|
| -// unless a full-fledged proxy description was discovered in the dictionary.
|
| -// However, at the present time this does not support username or password.
|
| -// Checks first for a SOCKS proxy, then for HTTPS, then HTTP.
|
| -bool GetMacProxySettingsFromDictionary(ProxyInfo* proxy,
|
| - const CFDictionaryRef proxyDict) {
|
| - // the function result.
|
| - bool gotProxy = false;
|
| -
|
| -
|
| - // first we see if there's a SOCKS proxy in place.
|
| - gotProxy = p_getProxyInfoForTypeFromDictWithKeys(proxy,
|
| - PROXY_SOCKS5,
|
| - proxyDict,
|
| - kSCPropNetProxiesSOCKSEnable,
|
| - kSCPropNetProxiesSOCKSProxy,
|
| - kSCPropNetProxiesSOCKSPort);
|
| -
|
| - if (!gotProxy) {
|
| - // okay, no SOCKS proxy, let's look for https.
|
| - gotProxy = p_getProxyInfoForTypeFromDictWithKeys(proxy,
|
| - PROXY_HTTPS,
|
| - proxyDict,
|
| - kSCPropNetProxiesHTTPSEnable,
|
| - kSCPropNetProxiesHTTPSProxy,
|
| - kSCPropNetProxiesHTTPSPort);
|
| - if (!gotProxy) {
|
| - // Finally, try HTTP proxy. Note that flute doesn't
|
| - // differentiate between HTTPS and HTTP, hence we are using the
|
| - // same flute type here, ie. PROXY_HTTPS.
|
| - gotProxy = p_getProxyInfoForTypeFromDictWithKeys(
|
| - proxy, PROXY_HTTPS, proxyDict, kSCPropNetProxiesHTTPEnable,
|
| - kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort);
|
| - }
|
| - }
|
| - return gotProxy;
|
| -}
|
| -
|
| -// TODO(hughv) Update keychain functions. They work on 10.8, but are depricated.
|
| -#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
| -bool p_putPasswordInProxyInfo(ProxyInfo* proxy) {
|
| - bool result = true; // by default we assume we're good.
|
| - // for all we know there isn't any password. We'll set to false
|
| - // if we find a problem.
|
| -
|
| - // Ask the keychain for an internet password search for the given protocol.
|
| - OSStatus oss = 0;
|
| - SecKeychainAttributeList attrList;
|
| - attrList.count = 3;
|
| - SecKeychainAttribute attributes[3];
|
| - attrList.attr = attributes;
|
| -
|
| - attributes[0].tag = kSecProtocolItemAttr;
|
| - attributes[0].length = sizeof(SecProtocolType);
|
| - SecProtocolType protocol;
|
| - switch (proxy->type) {
|
| - case PROXY_HTTPS :
|
| - protocol = kSecProtocolTypeHTTPS;
|
| - break;
|
| - case PROXY_SOCKS5 :
|
| - protocol = kSecProtocolTypeSOCKS;
|
| - break;
|
| - default :
|
| - LOG(LS_ERROR) << "asked for proxy password for unknown proxy type.";
|
| - result = false;
|
| - break;
|
| - }
|
| - attributes[0].data = &protocol;
|
| -
|
| - UInt32 port = proxy->address.port();
|
| - attributes[1].tag = kSecPortItemAttr;
|
| - attributes[1].length = sizeof(UInt32);
|
| - attributes[1].data = &port;
|
| -
|
| - std::string ip = proxy->address.ipaddr().ToString();
|
| - attributes[2].tag = kSecServerItemAttr;
|
| - attributes[2].length = ip.length();
|
| - attributes[2].data = const_cast<char*>(ip.c_str());
|
| -
|
| - if (result) {
|
| - LOG(LS_INFO) << "trying to get proxy username/password";
|
| - SecKeychainSearchRef sref;
|
| - oss = SecKeychainSearchCreateFromAttributes(NULL,
|
| - kSecInternetPasswordItemClass,
|
| - &attrList, &sref);
|
| - if (0 == oss) {
|
| - LOG(LS_INFO) << "SecKeychainSearchCreateFromAttributes was good";
|
| - // Get the first item, if there is one.
|
| - SecKeychainItemRef iref;
|
| - oss = SecKeychainSearchCopyNext(sref, &iref);
|
| - if (0 == oss) {
|
| - LOG(LS_INFO) << "...looks like we have the username/password data";
|
| - // If there is, get the username and the password.
|
| -
|
| - SecKeychainAttributeInfo attribsToGet;
|
| - attribsToGet.count = 1;
|
| - UInt32 tag = kSecAccountItemAttr;
|
| - UInt32 format = CSSM_DB_ATTRIBUTE_FORMAT_STRING;
|
| - void *data;
|
| - UInt32 length;
|
| - SecKeychainAttributeList *localList;
|
| -
|
| - attribsToGet.tag = &tag;
|
| - attribsToGet.format = &format;
|
| - OSStatus copyres = SecKeychainItemCopyAttributesAndData(iref,
|
| - &attribsToGet,
|
| - NULL,
|
| - &localList,
|
| - &length,
|
| - &data);
|
| - if (0 == copyres) {
|
| - LOG(LS_INFO) << "...and we can pull it out.";
|
| - // now, we know from experimentation (sadly not from docs)
|
| - // that the username is in the local attribute list,
|
| - // and the password in the data,
|
| - // both without null termination but with info on their length.
|
| - // grab the password from the data.
|
| - std::string password;
|
| - password.append(static_cast<const char*>(data), length);
|
| -
|
| - // make the password into a CryptString
|
| - // huh, at the time of writing, you can't.
|
| - // so we'll skip that for now and come back to it later.
|
| -
|
| - // now put the username in the proxy.
|
| - if (1 <= localList->attr->length) {
|
| - proxy->username.append(
|
| - static_cast<const char*>(localList->attr->data),
|
| - localList->attr->length);
|
| - LOG(LS_INFO) << "username is " << proxy->username;
|
| - } else {
|
| - LOG(LS_ERROR) << "got keychain entry with no username";
|
| - result = false;
|
| - }
|
| - } else {
|
| - LOG(LS_ERROR) << "couldn't copy info from keychain.";
|
| - result = false;
|
| - }
|
| - SecKeychainItemFreeAttributesAndData(localList, data);
|
| - } else if (errSecItemNotFound == oss) {
|
| - LOG(LS_INFO) << "...username/password info not found";
|
| - } else {
|
| - // oooh, neither 0 nor itemNotFound.
|
| - LOG(LS_ERROR) << "Couldn't get keychain information, error code" << oss;
|
| - result = false;
|
| - }
|
| - } else if (errSecItemNotFound == oss) { // noop
|
| - } else {
|
| - // oooh, neither 0 nor itemNotFound.
|
| - LOG(LS_ERROR) << "Couldn't get keychain information, error code" << oss;
|
| - result = false;
|
| - }
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -
|
| -bool GetMacProxySettings(ProxyInfo* proxy) {
|
| - // based on the Apple Technical Q&A QA1234
|
| - // http://developer.apple.com/qa/qa2001/qa1234.html
|
| - CFDictionaryRef proxyDict = SCDynamicStoreCopyProxies(NULL);
|
| - bool result = false;
|
| -
|
| - if (proxyDict != NULL) {
|
| - // sending it off to another function makes it easier to unit test
|
| - // since we can make our own dictionary to hand to that function.
|
| - result = GetMacProxySettingsFromDictionary(proxy, proxyDict);
|
| -
|
| - if (result) {
|
| - result = p_putPasswordInProxyInfo(proxy);
|
| - }
|
| -
|
| - CFRelease(proxyDict);
|
| - } else {
|
| - LOG(LS_ERROR) << "SCDynamicStoreCopyProxies failed";
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -#endif // WEBRTC_MAC && !defined(WEBRTC_IOS)
|
| -
|
| -#ifdef WEBRTC_IOS
|
| -// iOS has only http proxy
|
| -bool GetiOSProxySettings(ProxyInfo* proxy) {
|
| -
|
| - bool result = false;
|
| -
|
| - CFDictionaryRef proxy_dict = CFNetworkCopySystemProxySettings();
|
| - if (!proxy_dict) {
|
| - LOG(LS_ERROR) << "CFNetworkCopySystemProxySettings failed";
|
| - return false;
|
| - }
|
| -
|
| - CFNumberRef proxiesHTTPEnable = (CFNumberRef)CFDictionaryGetValue(
|
| - proxy_dict, kCFNetworkProxiesHTTPEnable);
|
| - if (!p_isCFNumberTrue(proxiesHTTPEnable)) {
|
| - CFRelease(proxy_dict);
|
| - return false;
|
| - }
|
| -
|
| - CFStringRef proxy_address = (CFStringRef)CFDictionaryGetValue(
|
| - proxy_dict, kCFNetworkProxiesHTTPProxy);
|
| - CFNumberRef proxy_port = (CFNumberRef)CFDictionaryGetValue(
|
| - proxy_dict, kCFNetworkProxiesHTTPPort);
|
| -
|
| - // the data we need to construct the SocketAddress for the proxy.
|
| - std::string hostname;
|
| - int port;
|
| - if (p_convertHostCFStringRefToCPPString(proxy_address, hostname) &&
|
| - p_convertCFNumberToInt(proxy_port, &port)) {
|
| - // We have something enabled, with a hostname and a port.
|
| - // That's sufficient to set up the proxy info.
|
| - // Finally, try HTTP proxy. Note that flute doesn't
|
| - // differentiate between HTTPS and HTTP, hence we are using the
|
| - // same flute type here, ie. PROXY_HTTPS.
|
| - proxy->type = PROXY_HTTPS;
|
| -
|
| - proxy->address.SetIP(hostname);
|
| - proxy->address.SetPort(port);
|
| - result = true;
|
| - }
|
| -
|
| - CFRelease(proxy_dict);
|
| -
|
| - return result;
|
| -}
|
| -#endif // WEBRTC_IOS
|
| -
|
| -bool AutoDetectProxySettings(const char* agent, const char* url,
|
| - ProxyInfo* proxy) {
|
| -#if defined(WEBRTC_WIN)
|
| - return WinHttpAutoDetectProxyForUrl(agent, url, proxy);
|
| -#else
|
| - LOG(LS_WARNING) << "Proxy auto-detection not implemented for this platform";
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -bool GetSystemDefaultProxySettings(const char* agent, const char* url,
|
| - ProxyInfo* proxy) {
|
| -#if defined(WEBRTC_WIN)
|
| - return GetIeProxySettings(agent, url, proxy);
|
| -#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
| - return GetMacProxySettings(proxy);
|
| -#elif defined(WEBRTC_IOS)
|
| - return GetiOSProxySettings(proxy);
|
| -#else
|
| - // TODO: Get System settings if browser is not firefox.
|
| - return GetFirefoxProxySettings(url, proxy);
|
| -#endif
|
| -}
|
| -
|
| -bool GetProxySettingsForUrl(const char* agent, const char* url,
|
| - ProxyInfo* proxy, bool long_operation) {
|
| - UserAgent a = GetAgent(agent);
|
| - bool result;
|
| - switch (a) {
|
| - case UA_FIREFOX: {
|
| - result = GetFirefoxProxySettings(url, proxy);
|
| - break;
|
| - }
|
| -#if defined(WEBRTC_WIN)
|
| - case UA_INTERNETEXPLORER:
|
| - result = GetIeProxySettings(agent, url, proxy);
|
| - break;
|
| - case UA_UNKNOWN:
|
| - // Agent not defined, check default browser.
|
| - if (IsDefaultBrowserFirefox()) {
|
| - result = GetFirefoxProxySettings(url, proxy);
|
| - } else {
|
| - result = GetIeProxySettings(agent, url, proxy);
|
| - }
|
| - break;
|
| -#endif // WEBRTC_WIN
|
| - default:
|
| - result = GetSystemDefaultProxySettings(agent, url, proxy);
|
| - break;
|
| - }
|
| -
|
| - // TODO: Consider using the 'long_operation' parameter to
|
| - // decide whether to do the auto detection.
|
| - if (result && (proxy->autodetect ||
|
| - !proxy->autoconfig_url.empty())) {
|
| - // Use WinHTTP to auto detect proxy for us.
|
| - result = AutoDetectProxySettings(agent, url, proxy);
|
| - if (!result) {
|
| - // Either auto detection is not supported or we simply didn't
|
| - // find any proxy, reset type.
|
| - proxy->type = rtc::PROXY_NONE;
|
| - }
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -} // namespace rtc
|
|
|