/*
 * Autenticação segura utilizando AJAX
 *
 * Autor: Ernani José Camargo Azevedo
 *        ernaniaz@gmail.com
 * Data: 31/Out/2008
 * Licença: GPLv3
 */

function debugMsg ( message)
{
  // Localiza objeto:
  debug = document.getElementById('debug');

  // Adiciona mensagem na janela de debug:
  debug.innerHTML += '<br />' + message;

  // Scroll da janela para baixo:
  debug.scrollTop = debug.scrollHeight;
}

function createXMLHTTP ()
{
  // Navegadores Mozilla/Safari:
  if ( window.XMLHttpRequest)
  {
    xmlHttpReq = new XMLHttpRequest ();
    xmlHttpReq.overrideMimeType ( 'text/xml');
  } else {
    // Navegadores IE:
    if ( window.ActiveXObject)
    {
      // O IE utiliza Msxml2.XMLHTTP:
      var ActiveXName = 'Msxml2.XMLHTTP';

      // O IE 5.5 ou superior utiliza Microsoft.XMLHTTP:
      if ( navigator.appVersion.indexOf ( 'MSIE 5.5') >= 0)
      {
        ActiveXName = 'Microsoft.XMLHTTP';
      }

      // Tenta instanciar:
      try
      {
        xmlHttpReq = new ActiveXObject ( ActiveXName);
      }

      // Avisa que o ActiveX está desabilitado:
      catch ( e)
      {
        alert ( 'Suporte a script no ActiveX deve ser habilitado.');
        return false;
      }
    } else {
      // Quaisquer outro navegador não é suportado:
      alert ( 'O seu navegador não é suportado por este aplicativo.');
      return false;
    }
  }

  return xmlHttpReq;
}

function getChallenge ( username)
{
  var xmlHttpReq = false;

  // Instancia um novo objeto XMLHTTP:
  xmlHttpReq = createXMLHTTP ();
  if ( ! xmlHttpReq)
  {
    // Retorna falso:
    return false;
  }

  // Insere os valores no objeto e envia:
  xmlHttpReq.open ( 'POST', 'auth.php', false);
  xmlHttpReq.setRequestHeader ( 'Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
  xmlHttpReq.send ( 'usuario=' + escape ( username));

  // Verifica se ocorreu erro (código HTTP diferente de 200):
  if ( xmlHttpReq.status != 200)
  {
    // Mostra uma mensagem de erro:
    alert ( "Ocorreu um erro ao autenticar no sistema.");

    // Retorna falso:
    return false;
  }

  // Verifica se o valor retornado é válido (possui 64 bytes):
  if ( xmlHttpReq.responseText.length != 64)
  {
    // Mostra uma mensagem de erro:
    alert ( "Ocorreu um erro ao autenticar no sistema.");

    // Retorna falso:
    return false;
  }

  // Retorna o valor randômico recebido do servidor:
  return xmlHttpReq.responseText;
}

function doLogin ( username, hash)
{
  var xmlHttpReq = false;

  // Instancia um novo objeto XMLHTTP:
  xmlHttpReq = createXMLHTTP ();

  // Insere os valores no objeto e envia:
  xmlHttpReq.open ( 'POST', 'auth.php', false);
  xmlHttpReq.setRequestHeader ( 'Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
  xmlHttpReq.send ( 'usuario=' + escape ( username) + '&hash=' + escape ( hash));

  // Verifica se ocorreu erro (código HTTP diferente de 200):
  if ( xmlHttpReq.status != 200)
  {
    // Mostra uma mensagem de erro:
    alert ( "Ocorreu um erro ao autenticar no sistema.");

    // Retorna falso:
    return false;
  }

  // Retorna o resultado:
  return xmlHttpReq.responseText;
}

function handleLogin ( form)
{
  // Recupera informações da autenticação do formulário informado:
  username = document.getElementById('login_username').value;
  password = document.getElementById('login_password').value;

  // Retorna caso não seja informado o usuário:
  if ( ! username)
  {
    return false;
  }

  // Desabilita o botão de envio de formulário para evitar envio duplicado:
  document.getElementById('ok_button').disabled = true;
  document.getElementById('ok_button').value = 'Autenticando...';

  // Requisita o desafio:
  debugMsg ( '');
  debugMsg ( 'Requisitando desafio para o usuário "' + username + '"');
  challenge = getChallenge ( username);
  debugMsg ( 'Recebido o desafio "' + challenge + '"');

  // Envia requisição de autenticação:
  debugMsg ( 'Enviando requisição de autenticação utilizando senha "' + password + '"');
  debugMsg ( 'Informações enviadas: usuario = "' + username + '", hash = "' + hex_sha256 ( hex_sha256 ( password) + challenge) + '"');
  login = doLogin ( username, hex_sha256 ( hex_sha256 ( password) + challenge));

  // Verifica resultado:
  if ( login == '1')
  {
    // Autenticação bem sucedida:
    debugMsg ( 'Autenticação concluída com sucesso');
    alert ( 'Autenticado como "' + username + '"!');
  } else {
    // Autenticação falhou. Exibe mensagem de erro:
    debugMsg ( 'Falha na autenticação');
    alert ( 'Falha na autenticação!');

    // Limpa o campo de senha:
    document.getElementById('login_password').value = "";

    // Seta o foco do navegador para o campo de senha:
    document.getElementById('login_password').focus ();
  }

  // Habilita o botão de autenticação do sistema:
  document.getElementById('ok_button').disabled = false;
  document.getElementById('ok_button').value = 'Autenticar';

  // Exibe mensagem de depuração:
  debugMsg ( 'Autenticação finalizada');

  // Retorna falso:
  return false;
}
