////////////////////////////////////////////////////////////////
// Login
////////////////////////////////////////////////////////////////

// the Login class includes XML messaging and error reporting code
// copied from hx:javax.baja.hx.hx.js - this code should eventually
// be refactored into common code, or at least kept in sync
// periodically
var login = new Login();

function Login()
{
////////////////////////////////////////////////////////////////
// Attributes
////////////////////////////////////////////////////////////////

  this.ie = navigator.appName.toLowerCase() == "microsoft internet explorer";
  this.failure = false;

  // Error
  this.err_LostConnection   = "Session disconnected";
  this.errorInvokeCode      = null;
  this.lastException        = null;
  this.lastExceptionDetails = null;
  this.lastExceptionMessage = null;
  
  // Login
  this.nonce                = null;
  
  this.handleNonceResponse = function(resp)
  {
    login.nonce = resp.responseText;
  }
  
  this.doLogin = function()
  {
    var scheme   = document.getElementById("scheme").value;
    var username = document.getElementById("username").value;
    var password = document.getElementById("password").value;
   
    var token;
   
    if (scheme == "cookieDigest") 
    {
      var msg = new SynchronousMessage();
      msg.setHeader("Content-Type", "application/x-niagara-login-support");
      msg.send(window.location, "action=getnonce", this.handleNonceResponse);
      token = base64encode(username + ":" + this.nonce + ":" + hex_sha1(hex_sha1(username + ":" + password) + ":" + this.nonce));
    } 
    else
    {
      token = base64encode(username + ":" + password);
    }  
    document.getElementById("token").value = token;
   
    // Nuke these textfields just in case a custom template
    // assigned 'name' attributes, which would send these
    // values over the wire in plain text 
    document.getElementById("username").value = "";
    document.getElementById("password").value = ""; 
    return true; 
  }
  

////////////////////////////////////////////////////////////////
// Error
////////////////////////////////////////////////////////////////

  /**
   * Handle error.
   */
  this.doError = function(msg, details, exception)
  {

 // Make sure exception is valid
    if (exception == null) exception = new Object();
    
 // ONLY EFFECTS MOZILLA BROWSERS 
 //   If an ajax request is currently being processed and the user
 //   attempts to navigate else where, then this error is thrown
 //   (Mozilla).
    if (exception.name == 'NS_ERROR_NOT_AVAILABLE') return;
   
    //Issue 13517 - hook for profile to try and handle the error more gracefully
    try
    {
      if(login.errorInvokeCode != null)
      {
        login.lastException=exception;
        login.lastExceptionDetails=details;
        login.lastExceptionMessage=msg;
        if(eval(login.errorInvokeCode))
          return;
      }
    }  
    catch(err)
    {
    
    }
    finally
    {
      login.lastException=null;          
      login.lastExceptionDetails=null;
      login.lastExceptionMessage=null;
    }
    
    var fileName = "undefined";
    var lineNumber = "undefined";
    var stack = "undefined";
    try
    {
      fileName = exception.fileName;
      lineNumber = exception.lineNumber;
      stack = exception.stack;
    }
    catch (err)
    {
      // If this throws an exception, we got one of those
      // internal exception things in Mozilla
      stack = exception;
    }

    // Default message if not set
    if (msg == null)
      msg = exception.name + ": " + exception.message;

    while (document.body.childNodes.length > 0)
      document.body.removeChild(document.body.firstChild);

    // Force style so we don't get anything weird
    var style = document.body.style;
    style.color = "black";
    style.background = "white";
    style.font = "normal 11px Tahoma";
    style.padding = "10px";

    var html = "<div style='font:18px Tahoma; padding-bottom:5px;'>";
    html += "Cannot display page</div>";
    html += msg + "<br/><br/>";
    html += "<div style='color:blue; cursor:pointer; text-decoration:underline;'";
    html += "onclick='document.getElementById(\"details\").";
    html += "style.visibility=\"visible\";'>";
    html += "Show Details</div>";
    html += "<div id='details' style='visibility:hidden; margin-top:10px;'>";

    // Exception information
    html += "<table width='100%' cellspacing='0' cellpadding='3'";
    html += " style='border:1px solid #666;'>";
    html += "<tr>";
    html += " <td colspan='2' style='background:#ccc;'>";
    html += "  <b>" + exception.name + ": " + exception.message + "</b>";
    html += " </td>";
    html += "</tr>";

    html += "<tr>";
    html += " <td style='background:#ddd;'><b>File:</b></td>";
    html += " <td width='100%' style='background:#eee;'>" + fileName + "</td>";
    html += "</tr>";

    html += "<tr>";
    html += " <td style='background:#ddd;'><b>Line:</b></td>";
    html += " <td style='background:#eee;'>" + lineNumber + "</td>";
    html += "</tr>";

    html += "<tr>";
    html += " <td valign='top' style='background:#ddd;'><b>Stack:</b></td>";
    html += " <td style='background:#eee;'>" + stack + "</td>";
    html += "</tr>";
    html += "</table>";

    // Details if they exist
    if (details != null && details.length > 0)
    {
      html += "<div style='margin-top:10px; padding:5px; background:#eee; ";
      html += "border:1px solid #666;'>";
      html += details;
      html += "</div>";
    }

    html += "</div>";
    document.body.innerHTML = html;
    login.failure = true;
  }
}


////////////////////////////////////////////////////////////////
// XmlHttp
////////////////////////////////////////////////////////////////

function SynchronousMessage()
{
  var headers = new Array();
  var responseHandler = null;
  var xmlhttp = (login.ie)
    ? new ActiveXObject("Msxml2.XMLHTTP")
    : new XMLHttpRequest();

  /**
   * Set the specified HTTP header.
   */
  this.setHeader = function(name, value)
  {
    headers.push({name:name, value:value });
  }

  /**
   * Send a message.
   */
  this.send = function(url, body, handler)
  {
    try
    {
      responseHandler = handler;
      xmlhttp.open("post", url, false);
      for (var i=0; i<headers.length; i++)
      {
        var header = headers[i];
        xmlhttp.setRequestHeader(header.name, header.value);
      }
      xmlhttp.setRequestHeader("Content-Length", body.length);

      // 24 Aug 07 - AndyF: Added for IE cache issues (when using a proxy server).
      if (login.ie)
        xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");

      xmlhttp.send(body);
      this.handleResponse();
    }
    catch (err)
    {
      login.doError("Message error", null, err);
    }
  }

  /**
   * Handle request response.
   */
  this.handleResponse = function()
  {
    try
    {
      if (xmlhttp.readyState == 4)
      {
        if (xmlhttp.status != "200")
        {
          var text = xmlhttp.responseText;
          if (text.length == 0) text = login.err_LostConnection;
          login.doError(text, null, null);
        }
        else if (responseHandler != null)
          responseHandler(xmlhttp);

        // 23 Oct 07 - AndyF: make sure we remove circular
        // dependancies to prevent memory leaks in IE
        xmlhttp.onreadystatechange = new function() {};
        xmlhttp = null;
      }
    }
    catch (err)
    {
      // 23 Oct 07 - AndyF: make sure we remove circular
      // dependancies to prevent memory leaks in IE
      xmlhttp.onreadystatechange = new function() {};
      xmlhttp = null;

      login.doError(login.err_LostConnection, null, err);
    }
  }
}

function init()
{
  document.getElementById("username").focus();
}

function doLogin(arg)
{
  return login.doLogin()
}

var encodeTable =
[
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
  'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
  'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  '0', '1', '2', '3', '4', '5', '6', '7', '8',
  '9', '+', '/', '='
];

function base64encode(inp)
{
  var out = ""; //This is the output
  var chr1, chr2, chr3 = ""; //These are the 3 bytes to be encoded
  var enc1, enc2, enc3, enc4 = ""; //These are the 4 encoded bytes
  var i = 0; //Position counter
  
  //Set up the loop here
  do
  { 
    chr1 = inp.charCodeAt(i++); //Grab the first byte
    chr2 = inp.charCodeAt(i++); //Grab the second byte
    chr3 = inp.charCodeAt(i++); //Grab the third byte
    
    //Here is the actual base64 encode part.
    //There really is only one way to do it.
    enc1 = chr1 >> 2;
    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
    enc4 = chr3 & 63;
    
    if (isNaN(chr2))
    {
      enc3 = enc4 = 64;
    }
    else if (isNaN(chr3))
    {
      enc4 = 64;
    }
  
    //Lets spit out the 4 encoded bytes
    out = out + encodeTable[enc1] + encodeTable[enc2] + encodeTable[enc3] + encodeTable[enc4];
  
    // OK, now clean out the variables used.
    chr1 = chr2 = chr3 = "";
    enc1 = enc2 = enc3 = enc4 = "";
  
  } while (i < inp.length); //And finish off the loop
  
  //Now return the encoded values.
  return out;
}



