// copyright (c) 2006-2008 Franz Inc, Oakland, CA - All rights reserved.
//
// The software, data and information contained herein are proprietary
// to, and comprise valuable trade secrets of, Franz, Inc.  They are
// given in confidence by Franz, Inc. pursuant to a written license
// agreement, and may be stored and used only in accordance with the terms
// of such license.
//
// Restricted Rights Legend
// ------------------------
// Use, duplication, and disclosure of the software, data and information
// contained herein by any agency, department or entity of the U.S.
// Government are subject to restrictions of Restricted Rights for
// Commercial Software developed at private expense as specified in
// DOD FAR Supplement 52.227-7013 (c) (1) (ii), as applicable.

// Need to encode characters as bytes before hashing them.
function utf8Encode(string) {
  string = string.replace(/\r\n/g,"\n");
  var bt = [];

  for (var n = 0; n < string.length; n++) {
    var c = string.charCodeAt(n);

    if (c < 128) {
      bt.push(c);
    }
    else if (c < 2048) {
      bt.push((c >> 6) | 192);
      bt.push(c & 63 | 128);
    }
    else if (c < 65536) {
      bt.push((c >> 12) | 224);
      bt.push((c >> 6) & 63 | 128);
      bt.push(c & 63 | 128);
    }
    else {
      bt.push((c >> 18) | 240);
      bt.push((c >> 12) & 63 | 128);
      bt.push((c >> 6) & 63 | 128);
      bt.push(c & 63 | 128);
    }
  }
  return bt;
};

// Regular SHA-1 hashing. Used for producing user credentials.
function SHA1(msg) {
  function rotate_left(n,s) {
    var t4 = (n<<s) | (n>>>(32-s));
    return t4;
  };
  function lsb_hex(val) {
    var str="";
    var i;
    var vh;
    var vl;
    for(i=0; i<=6; i+=2) {
      vh = (val>>>(i*4+4))&0x0f;
      vl = (val>>>(i*4))&0x0f;
      str += vh.toString(16) + vl.toString(16);
    }
    return str;
  };
  function cvt_hex(val) {
    var str="";
    var i;
    var v;
    for(i=7; i>=0; i--) {
      v = (val>>>(i*4))&0x0f;
      str += v.toString(16);
    }
    return str;
  };
  var blockstart;
  var i, j;
  var W = new Array(80);
  var H0 = 0x67452301;
  var H1 = 0xEFCDAB89;
  var H2 = 0x98BADCFE;
  var H3 = 0x10325476;
  var H4 = 0xC3D2E1F0;
  var A, B, C, D, E;
  var temp;
  msg = utf8Encode(msg);
  var msg_len = msg.length;
  var word_array = new Array();
  for(i=0; i<msg_len-3; i+=4) {
    j = msg[i]<<24 | msg[i+1]<<16 | msg[i+2]<<8 | msg[i+3];
    word_array.push(j);
  }
  switch(msg_len % 4) {
  case 0:
    i = 0x080000000;
    break;
  case 1:
    i = msg[msg_len-1]<<24 | 0x0800000;
    break;
  case 2:
    i = msg[msg_len-2]<<24 | msg[msg_len-1]<<16 | 0x08000;
    break;
  case 3:
    i = msg[msg_len-3]<<24 | msg[msg_len-2]<<16 | msg[msg_len-1]<<8 | 0x80;
    break;
  }
  word_array.push(i);
  while((word_array.length % 16) != 14) word_array.push(0);
  word_array.push(msg_len>>>29);
  word_array.push((msg_len<<3)&0x0ffffffff);
  for (blockstart=0; blockstart<word_array.length; blockstart+=16) {
    for(i=0; i<16; i++) W[i] = word_array[blockstart+i];
    for(i=16; i<=79; i++) W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
    A = H0;
    B = H1;
    C = H2;
    D = H3;
    E = H4;
    for(i= 0; i<=19; i++) {
      temp = (rotate_left(A,5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
      E = D;
      D = C;
      C = rotate_left(B,30);
      B = A;
      A = temp;
    }
    for(i=20; i<=39; i++) {
      temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
      E = D;
      D = C;
      C = rotate_left(B,30);
      B = A;
      A = temp;
    }
    for(i=40; i<=59; i++) {
      temp = (rotate_left(A,5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
      E = D;
      D = C;
      C = rotate_left(B,30);
      B = A;
      A = temp;
    }
    for(i=60; i<=79; i++) {
      temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
      E = D;
      D = C;
      C = rotate_left(B,30);
      B = A;
      A = temp;
    }
    H0 = (H0 + A) & 0x0ffffffff;
    H1 = (H1 + B) & 0x0ffffffff;
    H2 = (H2 + C) & 0x0ffffffff;
    H3 = (H3 + D) & 0x0ffffffff;
    H4 = (H4 + E) & 0x0ffffffff;
  }
  var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
  while (temp.length > 1 && temp.charAt(0) == "0") temp = temp.slice(1);
  return temp.toLowerCase();
}
