|  | /* | 
|  | * Copyright 2008 Google Inc. | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); you may not | 
|  | * use this file except in compliance with the License. You may obtain a copy of | 
|  | * the License at | 
|  | * | 
|  | * http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
|  | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
|  | * License for the specific language governing permissions and limitations under | 
|  | * the License. | 
|  | */ | 
|  |  | 
|  | #include "Debug.h" | 
|  | #include <string> | 
|  | #include <cstring> | 
|  | #include <vector> | 
|  |  | 
|  | #include "AllowedConnections.h" | 
|  |  | 
|  |  | 
|  | // TODO(jat): do we need to protect against parallel access to static state? | 
|  | //    current browsers only use one thread, but Chrome is multithreaded, though | 
|  | //    it isn't clear if plugins see parallel execution.  For now, we will | 
|  | //    assume the caller takes responsibility for making sure there are no | 
|  | //    concurrent calls into AllowedConnections. | 
|  | std::vector<AllowedConnections::Rule> AllowedConnections::rules; | 
|  |  | 
|  | /** | 
|  | * Get the host portion of the URL, not including the port. | 
|  | * | 
|  | * @return the host portion of the URL, or the unmodified URL if it does not appear | 
|  | *     to be valid | 
|  | */ | 
|  | std::string AllowedConnections::getHostFromUrl(const std::string& url) { | 
|  | int protoEnd = url.find("://"); | 
|  | if (protoEnd == std::string::npos) { | 
|  | Debug::log(Debug::Debugging) << "getHostFromUrl(" << url | 
|  | << ") - no :// in URL" << Debug::flush; | 
|  | return url; | 
|  | } | 
|  | protoEnd += 3; // skip over "://" | 
|  | int hostEnd = url.find('/', protoEnd); | 
|  | if (hostEnd == std::string::npos) { | 
|  | hostEnd = url.length(); | 
|  | } | 
|  | int colon = url.find(':', protoEnd); | 
|  | if (colon == std::string::npos || colon > hostEnd) { | 
|  | colon = hostEnd; | 
|  | } | 
|  | std::string host = url.substr(protoEnd, colon - protoEnd); | 
|  | return host; | 
|  | } | 
|  |  | 
|  | bool AllowedConnections::matchesRule(const std::string& url, | 
|  | bool* allowed) { | 
|  | std::string host = getHostFromUrl(url); | 
|  | // always allow localhost, localhost.* or 127.0.0.1 for the host | 
|  | // TODO(jat): try and get IP addresses of local interfaces? | 
|  | if (host == "localhost" || host.find("localhost.") == 0 | 
|  | || host == "127.0.0.1") { | 
|  | *allowed = true; | 
|  | return true; | 
|  | } | 
|  | Debug::log(Debug::Spam) << "Checking host " << host << Debug::flush; | 
|  | for (std::vector<AllowedConnections::Rule>::const_iterator it = rules.begin(); | 
|  | it != rules.end(); ++it) { | 
|  | Debug::log(Debug::Spam) << "  comparing to " << it->getPattern() | 
|  | << Debug::flush; | 
|  | // TODO(jat): add support for regexes | 
|  | if (host == it->getPattern()) { | 
|  | *allowed = !it->isExcluded(); | 
|  | return true; | 
|  | } | 
|  | } | 
|  | Debug::log(Debug::Info) | 
|  | << "GWT Development Mode connection requested by unknown web server " | 
|  | << host << Debug::flush; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void AllowedConnections::addRule(const std::string& pattern, | 
|  | bool exclude) { | 
|  | Debug::log(Debug::Spam) << "AllowedConnections::addRule(pattern=" << pattern | 
|  | << ", excl=" << exclude << ")" << Debug::flush; | 
|  | rules.push_back(AllowedConnections::Rule(pattern, exclude)); | 
|  | } | 
|  |  | 
|  | void AllowedConnections::clearRules() { | 
|  | rules.clear(); | 
|  | } | 
|  |  | 
|  | void AllowedConnections::initFromAccessList(const std::string& accessList) { | 
|  | clearRules(); | 
|  | int n = accessList.length(); | 
|  | for (int i = 0; i < n; ) { | 
|  | bool exclude = false; | 
|  | if (accessList[i] == '!') { | 
|  | exclude = true; | 
|  | ++i; | 
|  | } | 
|  | int comma = i - 1; // for pre-increment below | 
|  | while (++comma < n && accessList[comma] != ','); // empty | 
|  | addRule(accessList.substr(i, comma - i), exclude); | 
|  | i = comma + 1; | 
|  | } | 
|  | } |