diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 08:11:42 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 08:11:42 +0000 |
commit | f6fb2de77993bbd88931ba205b0cc1e3423111f6 (patch) | |
tree | 831dbc093048f60b7d3cfa6548d42cedc340b4d7 /net/proxy/proxy_server.cc | |
parent | 77c846f5d8043e56543668971fff356d58380cf7 (diff) | |
download | chromium_src-f6fb2de77993bbd88931ba205b0cc1e3423111f6.zip chromium_src-f6fb2de77993bbd88931ba205b0cc1e3423111f6.tar.gz chromium_src-f6fb2de77993bbd88931ba205b0cc1e3423111f6.tar.bz2 |
Add parsing for PAC result strings -- ProxyInfo::UsePacString().
Added the support class ProxyServer to avoid losing the proxy server's type information (http, socks) when populating the list.
The format of the configuration strings has been extended accordingly to include an optional [<scheme>"://"] prefix.
(i.e. "http://", "socks4://", "socks5://").
Review URL: http://codereview.chromium.org/20398
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10010 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/proxy/proxy_server.cc')
-rw-r--r-- | net/proxy/proxy_server.cc | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/net/proxy/proxy_server.cc b/net/proxy/proxy_server.cc new file mode 100644 index 0000000..d4f1f4e --- /dev/null +++ b/net/proxy/proxy_server.cc @@ -0,0 +1,215 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/proxy/proxy_server.h" + +#include "base/string_tokenizer.h" +#include "base/string_util.h" +#include "net/base/net_util.h" +#include "net/http/http_util.h" + +namespace net { + +namespace { + +// Returns the default port number for proxy server with the +// specified scheme. Returns -1 if unknown. +int GetDefaultPortForScheme(ProxyServer::Scheme scheme) { + switch (scheme) { + case ProxyServer::SCHEME_HTTP: + return 80; + case ProxyServer::SCHEME_SOCKS4: + case ProxyServer::SCHEME_SOCKS5: + return 1080; + default: + return -1; + } +} + +// Parse the proxy type from a PAC string, to a ProxyServer::Scheme. +// This mapping is case-insensitive. If no type could be matched +// returns SCHEME_INVALID. +ProxyServer::Scheme GetSchemeFromPacType(std::string::const_iterator begin, + std::string::const_iterator end) { + if (LowerCaseEqualsASCII(begin, end, "proxy")) + return ProxyServer::SCHEME_HTTP; + if (LowerCaseEqualsASCII(begin, end, "socks")) { + // Default to v4 for compatibility. This is because the SOCKS4 vs SOCKS5 + // notation didn't originally exist, so if a client returns SOCKS they + // really meant SOCKS4. + return ProxyServer::SCHEME_SOCKS4; + } + if (LowerCaseEqualsASCII(begin, end, "socks4")) + return ProxyServer::SCHEME_SOCKS4; + if (LowerCaseEqualsASCII(begin, end, "socks5")) + return ProxyServer::SCHEME_SOCKS5; + if (LowerCaseEqualsASCII(begin, end, "direct")) + return ProxyServer::SCHEME_DIRECT; + + return ProxyServer::SCHEME_INVALID; +} + +// Parse the proxy scheme from a URL-like representation, to a +// ProxyServer::Scheme. This corresponds with the values used in +// ProxyServer::ToURI(). If no type could be matched, returns SCHEME_INVALID. +ProxyServer::Scheme GetSchemeFromURI(std::string::const_iterator begin, + std::string::const_iterator end) { + if (LowerCaseEqualsASCII(begin, end, "http")) + return ProxyServer::SCHEME_HTTP; + if (LowerCaseEqualsASCII(begin, end, "socks4")) + return ProxyServer::SCHEME_SOCKS4; + if (LowerCaseEqualsASCII(begin, end, "socks5")) + return ProxyServer::SCHEME_SOCKS5; + if (LowerCaseEqualsASCII(begin, end, "direct")) + return ProxyServer::SCHEME_DIRECT; + return ProxyServer::SCHEME_INVALID; +} + +} // namespace + +const std::string& ProxyServer::host() const { + // Doesn't make sense to call this if the URI scheme doesn't + // have concept of a host. + DCHECK(is_valid() && !is_direct()); + return host_; +} + +int ProxyServer::port() const { + // Doesn't make sense to call this if the URI scheme doesn't + // have concept of a port. + DCHECK(is_valid() && !is_direct()); + return port_; +} + +std::string ProxyServer::host_and_port() const { + // Doesn't make sense to call this if the URI scheme doesn't + // have concept of a host. + DCHECK(is_valid() && !is_direct()); + return host_ + ":" + IntToString(port_); +} + +// static +ProxyServer ProxyServer::FromURI(const std::string& uri) { + return FromURI(uri.begin(), uri.end()); +} + +// static +ProxyServer ProxyServer::FromURI(std::string::const_iterator begin, + std::string::const_iterator end) { + // We will default to HTTP if no scheme specifier was given. + Scheme scheme = SCHEME_HTTP; + + // Trim the leading/trailing whitespace. + HttpUtil::TrimLWS(&begin, &end); + + // Check for [<scheme> "://"] + std::string::const_iterator colon = std::find(begin, end, ':'); + if (colon != end && + (end - colon) >= 3 && + *(colon + 1) == '/' && + *(colon + 2) == '/') { + scheme = GetSchemeFromURI(begin, colon); + begin = colon + 3; // Skip past the "://" + } + + // Now parse the <host>[":"<port>]. + return FromSchemeHostAndPort(scheme, begin, end); +} + +std::string ProxyServer::ToURI() const { + switch (scheme_) { + case SCHEME_DIRECT: + return "direct://"; + case SCHEME_HTTP: + // Leave off "http://" since it is our default scheme. + return host_and_port(); + case SCHEME_SOCKS4: + return std::string("socks4://") + host_and_port(); + case SCHEME_SOCKS5: + return std::string("socks5://") + host_and_port(); + default: + // Got called with an invalid scheme. + NOTREACHED(); + return std::string(); + } +} + +// static +ProxyServer ProxyServer::FromPacString(const std::string& pac_string) { + return FromPacString(pac_string.begin(), pac_string.end()); +} + +ProxyServer ProxyServer::FromPacString(std::string::const_iterator begin, + std::string::const_iterator end) { + // Trim the leading/trailing whitespace. + HttpUtil::TrimLWS(&begin, &end); + + // Input should match: + // "DIRECT" | ( <type> 1*(LWS) <host-and-port> ) + + // Start by finding the first space (if any). + std::string::const_iterator space; + for (space = begin; space != end; ++space) { + if (HttpUtil::IsLWS(*space)) { + break; + } + } + + // Everything to the left of the space is the scheme. + Scheme scheme = GetSchemeFromPacType(begin, space); + + // And everything to the right of the space is the + // <host>[":" <port>]. + return FromSchemeHostAndPort(scheme, space, end); +} + +std::string ProxyServer::ToPacString() const { + switch (scheme_) { + case SCHEME_DIRECT: + return "DIRECT"; + case SCHEME_HTTP: + return std::string("PROXY ") + host_and_port(); + case SCHEME_SOCKS4: + // For compatibility send SOCKS instead of SOCKS4. + return std::string("SOCKS ") + host_and_port(); + case SCHEME_SOCKS5: + return std::string("SOCKS5 ") + host_and_port(); + default: + // Got called with an invalid scheme. + NOTREACHED(); + return std::string(); + } +} + +// static +ProxyServer ProxyServer::FromSchemeHostAndPort( + Scheme scheme, + std::string::const_iterator begin, + std::string::const_iterator end) { + + // Trim leading/trailing space. + HttpUtil::TrimLWS(&begin, &end); + + if (scheme == SCHEME_DIRECT && begin != end) + return ProxyServer(); // Invalid -- DIRECT cannot have a host/port. + + std::string host; + int port = -1; + + if (scheme != SCHEME_INVALID && scheme != SCHEME_DIRECT) { + // If the scheme has a host/port, parse it. + bool ok = net::GetHostAndPort(begin, end, &host, &port); + if (!ok) + return ProxyServer(); // Invalid -- failed parsing <host>[":"<port>] + } + + // Choose a default port number if none was given. + if (port == -1) + port = GetDefaultPortForScheme(scheme); + + return ProxyServer(scheme, host, port); +} + +} // namespace net + |