/* -*- java -*- */

with ({
  LOG: function LOG(message) {
    dump("auth.js: " + message + "\n");
    Components
      .classes['@mozilla.org/consoleservice;1']
      .getService(Components.interfaces.nsIConsoleService)
      .logStringMessage("auth.js: " + message);
  }
}) {

  try {
    LOG("start.");

    var authScheme = "Mutual";

    var getPortFromUri = function getPortFromUri (uri) {
      if (uri.port != -1) {
        return uri.port;

      } else {
        try{
          var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                                    .getService(Components.interfaces.nsIIOService);
          var protocolHandler = ioService.getProtocolHandler(uri.scheme);

          return protocolHandler.defaultPort;
        }catch(ex) {
          LOG(ex);
          return -1;
        }
      }
    };

    var doAuth = function doAuth (uri, challengeStr, username, password) {
      LOG("doAuth");

      if(uri == undefined){
        LOG("*** ERROR ***: authUrl unknown");
        throw Components.results.NS_ERROR_UNEXPECTED;
      }
      if(challengeStr == undefined){
        LOG("*** ERROR ***: authChallenge unknown");
        throw Components.results.NS_ERROR_UNEXPECTED;
      }

      LOG("< " + uri.spec);
      LOG("< " + challengeStr);
      var challenge = mutualHeader.parseHeader(challengeStr);
      if(challenge == null){
        LOG("*** ERROR ***: challenge parse failed.");
        throw Components.results.NS_ERROR_UNEXPECTED;
      }

      if (mutualHeader.getHeaderType(challenge) != "401-B0") {
        LOG("*** ERROR ***: not 401-B0 challenge.");
        throw Components.results.NS_ERROR_UNEXPECTED;
      }

      var b0scheme     = challenge.scheme;
      var b0algorithm  = challenge.params["algorithm"];
      var b0validation = challenge.params["validation"];
      var b0realm      = challenge.params["realm"];
      var b0reason     = challenge.params["reason"];

      var b0authDomain = challenge.params["auth-domain"];
      var b0pwdHash    = challenge.params["pwd-hash"];

      var authDomain;
      var isDefaultAuthDomain;
      if (b0authDomain == undefined) {
        authDomain = uri.asciiHost;
        isDefaultAuthDomain = true;
      } else {
        authDomain = b0authDomain;
        isDefaultAuthDomain = false;
      }

      var pwdHash;
      if (b0pwdHash == undefined) {
        pwdHash = "none";
      } else {
        pwdHash = b0pwdHash;
      }

      var metadata = Components.classes["@lepidum.co.jp/mutual/session-state;1"]
                               .createInstance(Components.interfaces.nsIMutualSessionState);
      metadata.setIdentity(username, password);
      metadata.setParameters(pwdHash, b0validation);
      metadata.setRealm(b0algorithm, authDomain, b0realm, isDefaultAuthDomain);
      metadata.isFirstRequest = true;

      var path;
      try {
        var url = uri.QueryInterface(Components.interfaces.nsIURL);
        path = url.directory;
      } catch(ex) {
        path = uri.path;
      }

      var authManager = Components.classes["@mozilla.org/network/http-auth-manager;1"]
                                  .getService(Components.interfaces.nsIHttpAuthManager);
      authManager.clearPreemptiveAuthCache(
        uri.scheme,
        uri.asciiHost,
        getPortFromUri(uri),
        path
        );
      authManager.setAuthIdentityWithMetadataAndChallenge(
        uri.scheme,
        uri.asciiHost,
        getPortFromUri(uri),
        authScheme,
        b0realm,
        path,
        null,
        username,
        "",
        metadata,
        challengeStr
        );

      var loc = uri.spec;
      var hash = loc.indexOf('#');
      if (0 <= hash) {
        loc = loc.substring(0, hash);
      }
      content.location = loc;
    };

  } catch(ex) {
    LOG(ex);
  }
}
