зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1334443 - Rewrite nsProtocolProxyService::LoadHostFilters to use Tokenizer r=bagder
This eliminates some of the pointer math and makes the method a bit safer. The function's behaviour remains the same as before. MozReview-Commit-ID: 94wBk6xvkd6 --HG-- extra : rebase_source : 9fac33114b16d0910e63b474222acf0bc1db500f
This commit is contained in:
Родитель
179c07ad0e
Коммит
1d52489dd5
|
@ -36,6 +36,7 @@
|
|||
#include "nsINetworkLinkService.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Tokenizer.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
@ -646,7 +647,7 @@ nsProtocolProxyService::PrefsChanged(nsIPrefBranch *prefBranch,
|
|||
rv = prefBranch->GetCharPref(PROXY_PREF("no_proxies_on"),
|
||||
getter_Copies(tempString));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
LoadHostFilters(tempString.get());
|
||||
LoadHostFilters(tempString);
|
||||
}
|
||||
|
||||
// We're done if not using something that could give us a PAC URL
|
||||
|
@ -1470,15 +1471,16 @@ nsProtocolProxyService::GetProxyConfigType(uint32_t* aProxyConfigType)
|
|||
}
|
||||
|
||||
void
|
||||
nsProtocolProxyService::LoadHostFilters(const char *filters)
|
||||
nsProtocolProxyService::LoadHostFilters(const nsACString& aFilters)
|
||||
{
|
||||
// check to see the owners flag? /!?/ TODO
|
||||
if (mHostFiltersArray.Length() > 0) {
|
||||
mHostFiltersArray.Clear();
|
||||
}
|
||||
|
||||
if (!filters)
|
||||
return; // fail silently...
|
||||
if (aFilters.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// filter = ( host | domain | ipaddr ["/" mask] ) [":" port]
|
||||
|
@ -1486,38 +1488,79 @@ nsProtocolProxyService::LoadHostFilters(const char *filters)
|
|||
//
|
||||
// Reset mFilterLocalHosts - will be set to true if "<local>" is in pref string
|
||||
mFilterLocalHosts = false;
|
||||
while (*filters) {
|
||||
|
||||
mozilla::Tokenizer t(aFilters);
|
||||
mozilla::Tokenizer::Token token;
|
||||
bool eof = false;
|
||||
// while (*filters) {
|
||||
while (!eof) {
|
||||
// skip over spaces and ,
|
||||
while (*filters && (*filters == ',' || IS_ASCII_SPACE(*filters)))
|
||||
filters++;
|
||||
|
||||
const char *starthost = filters;
|
||||
const char *endhost = filters + 1; // at least that...
|
||||
const char *portLocation = 0;
|
||||
const char *maskLocation = 0;
|
||||
|
||||
while (*endhost && (*endhost != ',' && !IS_ASCII_SPACE(*endhost))) {
|
||||
if (*endhost == ':')
|
||||
portLocation = endhost;
|
||||
else if (*endhost == '/')
|
||||
maskLocation = endhost;
|
||||
else if (*endhost == ']') // IPv6 address literals
|
||||
portLocation = 0;
|
||||
endhost++;
|
||||
t.SkipWhites();
|
||||
while (t.CheckChar(',')) {
|
||||
t.SkipWhites();
|
||||
}
|
||||
|
||||
filters = endhost; // advance iterator up front
|
||||
nsAutoCString portStr;
|
||||
nsAutoCString hostStr;
|
||||
nsAutoCString maskStr;
|
||||
t.Record();
|
||||
|
||||
// locate end of host
|
||||
const char *end = maskLocation ? maskLocation :
|
||||
portLocation ? portLocation :
|
||||
endhost;
|
||||
bool parsingIPv6 = false;
|
||||
bool parsingPort = false;
|
||||
bool parsingMask = false;
|
||||
while (t.Next(token)) {
|
||||
if (token.Equals(mozilla::Tokenizer::Token::EndOfFile())) {
|
||||
eof = true;
|
||||
break;
|
||||
}
|
||||
if (token.Equals(mozilla::Tokenizer::Token::Char(',')) ||
|
||||
token.Type() == mozilla::Tokenizer::TOKEN_WS) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString str(starthost, end - starthost);
|
||||
if (token.Equals(mozilla::Tokenizer::Token::Char('['))) {
|
||||
parsingIPv6 = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parsingIPv6 && token.Equals(mozilla::Tokenizer::Token::Char(':'))) {
|
||||
// Port is starting. Claim the previous as host.
|
||||
if (parsingMask) {
|
||||
t.Claim(maskStr);
|
||||
} else {
|
||||
t.Claim(hostStr);
|
||||
}
|
||||
t.Record();
|
||||
parsingPort = true;
|
||||
continue;
|
||||
} else if (token.Equals(mozilla::Tokenizer::Token::Char('/'))) {
|
||||
t.Claim(hostStr);
|
||||
t.Record();
|
||||
parsingMask = true;
|
||||
continue;
|
||||
} else if (token.Equals(mozilla::Tokenizer::Token::Char(']'))) {
|
||||
parsingIPv6 = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!parsingPort && !parsingMask) {
|
||||
t.Claim(hostStr);
|
||||
} else if (parsingPort) {
|
||||
t.Claim(portStr);
|
||||
} else if (parsingMask) {
|
||||
t.Claim(maskStr);
|
||||
} else {
|
||||
NS_WARNING("Could not parse this rule");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hostStr.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the current host filter is "<local>", then all local (i.e.
|
||||
// no dots in the hostname) hosts should bypass the proxy
|
||||
if (str.EqualsIgnoreCase("<local>")) {
|
||||
if (hostStr.EqualsIgnoreCase("<local>")) {
|
||||
mFilterLocalHosts = true;
|
||||
LOG(("loaded filter for local hosts "
|
||||
"(plain host names, no dots)\n"));
|
||||
|
@ -1527,19 +1570,30 @@ nsProtocolProxyService::LoadHostFilters(const char *filters)
|
|||
|
||||
// For all other host filters, create HostInfo object and add to list
|
||||
HostInfo *hinfo = new HostInfo();
|
||||
hinfo->port = portLocation ? atoi(portLocation + 1) : 0;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
int32_t port = portStr.ToInteger(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
port = 0;
|
||||
}
|
||||
hinfo->port = port;
|
||||
|
||||
int32_t maskLen = maskStr.ToInteger(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
maskLen = 128;
|
||||
}
|
||||
|
||||
// PR_StringToNetAddr can't parse brackets enclosed IPv6
|
||||
nsAutoCString addrString = str;
|
||||
if (str.Length() > 0 && str.First() == '[' && str.Last() == ']') {
|
||||
addrString = Substring(str, 1, str.Length() - 2);
|
||||
nsAutoCString addrString = hostStr;
|
||||
if (hostStr.First() == '[' && hostStr.Last() == ']') {
|
||||
addrString = Substring(hostStr, 1, hostStr.Length() - 2);
|
||||
}
|
||||
|
||||
PRNetAddr addr;
|
||||
if (PR_StringToNetAddr(addrString.get(), &addr) == PR_SUCCESS) {
|
||||
hinfo->is_ipaddr = true;
|
||||
hinfo->ip.family = PR_AF_INET6; // we always store address as IPv6
|
||||
hinfo->ip.mask_len = maskLocation ? atoi(maskLocation + 1) : 128;
|
||||
hinfo->ip.mask_len = maskLen;
|
||||
|
||||
if (hinfo->ip.mask_len == 0) {
|
||||
NS_WARNING("invalid mask");
|
||||
|
@ -1566,20 +1620,25 @@ nsProtocolProxyService::LoadHostFilters(const char *filters)
|
|||
proxy_MaskIPv6Addr(hinfo->ip.addr, hinfo->ip.mask_len);
|
||||
}
|
||||
else {
|
||||
uint32_t startIndex, endIndex;
|
||||
if (str.First() == '*')
|
||||
startIndex = 1; // *.domain -> .domain
|
||||
else
|
||||
startIndex = 0;
|
||||
endIndex = (portLocation ? portLocation : endhost) - starthost;
|
||||
nsAutoCString host;
|
||||
if (hostStr.First() == '*') {
|
||||
host = Substring(hostStr, 1);
|
||||
} else {
|
||||
host = hostStr;
|
||||
}
|
||||
|
||||
if (host.IsEmpty()) {
|
||||
hinfo->name.host = nullptr;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
hinfo->name.host_len = host.Length();
|
||||
|
||||
hinfo->is_ipaddr = false;
|
||||
hinfo->name.host = ToNewCString(Substring(str, startIndex, endIndex));
|
||||
hinfo->name.host = ToNewCString(host);
|
||||
|
||||
if (!hinfo->name.host)
|
||||
goto loser;
|
||||
|
||||
hinfo->name.host_len = endIndex - startIndex;
|
||||
}
|
||||
|
||||
//#define DEBUG_DUMP_FILTERS
|
||||
|
@ -1587,6 +1646,7 @@ nsProtocolProxyService::LoadHostFilters(const char *filters)
|
|||
printf("loaded filter[%zu]:\n", mHostFiltersArray.Length());
|
||||
printf(" is_ipaddr = %u\n", hinfo->is_ipaddr);
|
||||
printf(" port = %u\n", hinfo->port);
|
||||
printf(" host = %s\n", hostStr.get());
|
||||
if (hinfo->is_ipaddr) {
|
||||
printf(" ip.family = %x\n", hinfo->ip.family);
|
||||
printf(" ip.mask_len = %u\n", hinfo->ip.mask_len);
|
||||
|
|
|
@ -274,7 +274,7 @@ protected:
|
|||
* @param hostFilters
|
||||
* A "no-proxy-for" exclusion list.
|
||||
*/
|
||||
void LoadHostFilters(const char *hostFilters);
|
||||
void LoadHostFilters(const nsACString& hostFilters);
|
||||
|
||||
/**
|
||||
* This method checks the given URI against mHostFiltersArray.
|
||||
|
|
|
@ -88,7 +88,7 @@ TEST(TestProtocolProxyService, LoadHostFilters) {
|
|||
|
||||
// Anything is allowed when there are no filters set
|
||||
printf("Testing empty filter: %s\n", filter.get());
|
||||
pps->LoadHostFilters(filter.get());
|
||||
pps->LoadHostFilters(filter);
|
||||
|
||||
CheckLoopbackURLs(true); // only time when loopbacks can be proxied. bug?
|
||||
CheckLocalDomain(true);
|
||||
|
@ -99,7 +99,7 @@ TEST(TestProtocolProxyService, LoadHostFilters) {
|
|||
|
||||
filter = "example.com, 1.2.3.4/16, [2001::1], 10.0.0.0/8, 2.3.0.0/16:7777, [abcd::1]/64:123, *.test.com";
|
||||
printf("Testing filter: %s\n", filter.get());
|
||||
pps->LoadHostFilters(filter.get());
|
||||
pps->LoadHostFilters(filter);
|
||||
// Check URLs can no longer use filtered proxy
|
||||
CheckURLs(false);
|
||||
CheckLoopbackURLs(false);
|
||||
|
@ -112,11 +112,16 @@ TEST(TestProtocolProxyService, LoadHostFilters) {
|
|||
// backwards compatibility.
|
||||
filter = "<local> blabla.com:10";
|
||||
printf("Testing filter: %s\n", filter.get());
|
||||
pps->LoadHostFilters(filter.get());
|
||||
pps->LoadHostFilters(filter);
|
||||
CheckURLs(true);
|
||||
CheckLoopbackURLs(false);
|
||||
CheckLocalDomain(false);
|
||||
CheckPortDomain(false);
|
||||
|
||||
// Check that we don't crash on weird input
|
||||
filter = "a b c abc:1x2, ,, * ** *.* *:10 :20 :40/12 */12:90";
|
||||
printf("Testing filter: %s\n", filter.get());
|
||||
pps->LoadHostFilters(filter);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
|
|
Загрузка…
Ссылка в новой задаче