FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
SystemProxyDetectorWin.cpp
1 
2 #include "win_targetver.h"
3 #include "win_common.h"
4 #include "Win/SystemProxyDetectorWin.h"
5 #include <boost/scoped_ptr.hpp>
6 #include <boost/scoped_array.hpp>
7 #include <sstream>
8 #include <URI.h>
9 #include "logging.h"
10 #include "../precompiled_headers.h" // On windows, everything above this line in PCH
11 
12 #include <boost/algorithm/string.hpp>
13 #include <wininet.h>
14 #include <vector>
15 
16 using boost::algorithm::split;
17 using boost::algorithm::is_any_of;
18 using std::string;
19 using std::vector;
20 using std::map;
21 
22 FB::SystemProxyDetector* FB::SystemProxyDetector::get()
23 {
24  static boost::scoped_ptr<FB::SystemProxyDetector> _inst(new FB::SystemProxyDetectorWin());
25  return _inst.get();
26 }
27 
28 namespace {
29 
30  string lastError(const char* fnname) {
31  DWORD errcode = GetLastError();
32  char* buf = NULL;
33  FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
34  NULL, errcode, 0, (LPSTR)&buf, 0, NULL);
35 
36  std::stringstream stream;
37  stream << fnname << ": " << buf;
38  LocalFree(buf);
39  return stream.str();
40  }
41 
42  void throw_GetLastError(const char* fnname) {
43  throw std::runtime_error(lastError(fnname).c_str());
44  }
45 
46 }
47 
48 bool FB::SystemProxyDetectorWin::detectProxy( map<string, string>& proxyMap, const string& URL )
49 {
50  proxyMap.clear();
51  try {
52  // The buffer that InternetQueryOption wants contains all of the strings after the struct in one
53  // alloc, that's why this is variable size instead of just sizeof(INTERNET_PROXY_INFO)
54  DWORD ipiSize = 0;
55  InternetQueryOption(NULL, INTERNET_OPTION_PROXY, NULL, &ipiSize);
56  boost::scoped_array<char> ipiBuf(new char[ipiSize]);
57  INTERNET_PROXY_INFO* ipi = reinterpret_cast<INTERNET_PROXY_INFO*>(ipiBuf.get());
58 
59  if (! InternetQueryOption(NULL, INTERNET_OPTION_PROXY, ipiBuf.get(), &ipiSize)) throw_GetLastError("InternetQueryOption(INTERNET_OPTION_PROXY)");
60 
61  if (ipi->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
62  FB::URI uri(FB::URI::fromString(URL));
63  // Proxy config looks like:
64  // socks=socks_proxy_server:1080 https=https_proxy_server:4443 ftp=ftp_proxy_server:2222 http=http_proxy_server:3128
65  // any of the key-value pairs may be omitted
66  // or, if it's just a single proxy server (which is HTTP):
67  // http_proxy_server:3128
68 
69  string proxyConfig(reinterpret_cast<const char*>(ipi->lpszProxy));
70 
71  vector<string> proxy_parts;
72  split(proxy_parts, proxyConfig, is_any_of(" "));
73  for (size_t i = 0; i < proxy_parts.size(); ++i) {
74  vector<string> kvp;
75  split(kvp, proxy_parts[i], is_any_of("="));
76  if (kvp.empty()) continue;
77  if (kvp.size() == 1) {
78  // untyped proxy entry. just put http on the front of the array, then fall through to the other case
79  if (uri.protocol == "https") {
80  // handling case when 'Use the same proxy for all protocols'
81  // selected in WinInet settings
82  kvp.insert(kvp.begin(), string("https"));
83  } else {
84  kvp.insert(kvp.begin(), string("http"));
85  }
86  }
87 
88  // this is a typed proxy entry. kvp[0] should be one of {socks,https,ftp,http}
89  vector<string> host_parts;
90  split(host_parts, kvp[1], is_any_of(":"));
91  if (host_parts.size() < 2) continue; // what?
92 
93  if (kvp[0] == uri.protocol || (proxyMap.find("type") == proxyMap.end() && kvp[0] == "socks")) {
94  // If we find a match for this exact protocol *or* if there is a socks proxy
95  proxyMap["port"] = host_parts[1];
96  proxyMap["hostname"] = host_parts[0];
97  proxyMap["type"] = kvp[0];
98  }
99  }
100  }
101  return proxyMap.find("type") != proxyMap.end();
102  } catch (const std::exception& e) {
103  // TODO: This isn't a very good place to log this.
104  FBLOG_WARN("SystemProxyDetector", "Could not detect system proxy: " << e.what());
105  return false;
106  }
107 }
static URI fromString(const std::string &in_str)
Returns a URI object from the given string.
Definition: URI.cpp:90
Data structure for dealing with URI strings.
Definition: URI.h:42