/*
 * 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();
  }
  //skip over user:passwd@ if it exists
  int userPassword = url.find( '@', protoEnd );
  if (userPassword == std::string::npos || userPassword > hostEnd)
  {
    userPassword = protoEnd;
  }

  int colon = url.find(':', userPassword);
  if (colon == std::string::npos || colon > hostEnd) {
    colon = hostEnd;
  }
  std::string host = url.substr(userPassword, colon - userPassword);
  return host;
}

std::string AllowedConnections::getCodeServerFromUrl(const std::string& url) {
  int queryStart = url.find("?");
  if (queryStart == std::string::npos) {
    Debug::log(Debug::Debugging) << "getCodeServerFromUrl(" << url
        << ") - no ? in URL" << Debug::flush;
    return "";
  }
  ++queryStart; //skip the ?

  int paramStart = url.find("gwt.codesvr=", queryStart);
  if (paramStart == std::string::npos) {
    Debug::log(Debug::Debugging) << "getCodeServerFromUrl(" << url
        << ") - missing gwt.codesvr in URL" << Debug::flush;
    return "";
  }
  paramStart += 12;

  int colon = url.find(':', paramStart);
  // After navigation, the URL parameter could be encoded.
  // ex: gwt.codesvr=127.0.0.1:9997 -> gwt.codesvr=127.0.0.1%3A9997.
  int colonEncoded = url.find("%3A", paramStart);
  if (colonEncoded != std::string::npos
      && (colon == std::string::npos || colonEncoded < colon)) {
    colon = colonEncoded;
  }

  int variableEnd = url.find('&', paramStart);
  if ( variableEnd == std::string::npos || colon < variableEnd) {
    variableEnd = colon; //could be std::string::npos!
  }
  Debug::log(Debug::Spam) << "getCodeServerFromUrl(" << url
      << ") - gwt.codesvr=" <<
      url.substr(paramStart, variableEnd-paramStart) << " in URL"
      << Debug::flush;

  return url.substr(paramStart, variableEnd-paramStart);
}

bool AllowedConnections::matchesRule(const std::string& webHost,
                                     const std::string& codeServer,
                                     bool* allowed) {
  std::string host = webHost;
  std::string server = codeServer;

  //Remap variants of localhost
  if (host.find("localhost.") == 0 || host == "127.0.0.1") {
    host = "localhost";
  }

  if (server.find("localhost.") == 0 || server == "127.0.0.1" )
  {
    server = "localhost";
  }

  // always allow localhost
  // TODO(jat): try and get IP addresses of local interfaces?
  if (host == "localhost" && server == "localhost") {
    *allowed = true;
    return true;
  }

  Debug::log(Debug::Spam) << "Checking webHost(" << webHost
      << "), codeServer(" << codeServer << ") " << Debug::flush;
  for (std::vector<AllowedConnections::Rule>::const_iterator it = rules.begin();
       it != rules.end(); ++it) {
    Debug::log(Debug::Spam) << "  comparing to webHost=(" << it->getWebHost()
        << ") codeServer=(" << it->getCodeServer() << ")" << Debug::flush;
    // TODO(jat): add support for regexes
  if (webHost == it->getWebHost() && codeServer == it->getCodeServer()) {
      *allowed = !it->isExcluded();
      Debug::log(Debug::Spam) << "    found! allowed=" << *allowed
          << Debug::flush;
      return true;
    }
  }
  Debug::log(Debug::Info)
      << "GWT Development Mode connection requested by unknown web server "
      << webHost << ", code server " << codeServer << Debug::flush;
  return false;
}

void AllowedConnections::addRule(const std::string& webHost, 
                                 const std::string& codeServer, 
                                 bool exclude) {
  Debug::log(Debug::Spam) << "AllowedConnections::addRule(webHost=" << webHost
      << ", codeServer=" << codeServer << ", excl=" << exclude << ")"
      << Debug::flush;
  rules.push_back(AllowedConnections::Rule(webHost, codeServer, exclude));
}

void AllowedConnections::clearRules() {
  rules.clear();
}

void AllowedConnections::initFromAccessList(const std::string& accessList) {
  Debug::log(Debug::Spam) << "initFromAccessList() accessList="
      << accessList << Debug::flush;
  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
    std::string option = accessList.substr(i, comma - i);
    i = comma + 1;

    //parse the [/codeserver] optional element
    int slash = option.find( '/');
    if( slash == std::string::npos ) {
      addRule(option, "localhost", exclude);
    } else {
      addRule(option.substr(0, slash), option.substr(slash+1), exclude);
    }
  }
}
