﻿use array;

function tos32(n) // to signed 32-bit integer
 while n>0x7fffffff do n-=0x100000000 end;
 return n;
end;

function tou32(n) // to unsigned 32-bit integer
 while n<0 do n+=0x100000000 end;
 return n;
end;

function shrr(n,s) // Zero-fill right shift (the >>> with JS)
 a = n shr s;
 b = 0;
 for i=1 to (32-s) do
 	b = (b shl 1) | 1;
 end;
 return a & b;
end;

function rotate_left(n,s)
  t4 = (n shl s) | (shrr(n,(32-s)));
  return t4;
end;

function cvt_hex(val)
/*  s = "";
  v = 0;
  for i=7 to 0 by -1 do
    v = shrr(val,i*4) & 0x0f;
    s = s + hexstr(v);
  end;
  return s; */
  return hexstr(tou32(val),8);
end;

function Utf8Encode(s)
  s = replace(s,"\r\n","\n");
  utftext = "";
  for n=0 to len(s)-1 do
    c = code(s,n);
    if c < 128 then
      utftext = utftext + char(c);
    elsif ((c > 127) and (c < 2048)) then
      utftext = utftext + char((c shr 6) | 192);
      utftext = utftext + char((c & 63) | 128);
    else
      utftext = utftext + char((c shr 12) | 224);
      utftext = utftext + char(((c shr 6) & 63) | 128);
      utftext = utftext + char((c & 63) | 128);
    end;
  end;
  return utftext;
end;

function SHA1(msg)
// From http://www.webtoolkit.info/javascript-sha1.html
W = array.create(80,0);
H0 = tos32(0x67452301);
H1 = tos32(0xefcdab89);
H2 = tos32(0x98badcfe);
H3 = tos32(0x10325476);
H4 = tos32(0xc3d2e1f0);

msg_len = len(msg);

word_array = array.new();
for i = 0 to msg_len-4 by 4 do
  j = (code(msg,i) shl 24) | (code(msg,i+1) shl 16) | (code(msg,i+2) shl 8) | code(msg,i+3);
  append(word_array,j);
end;

case (msg_len % 4)
in 0: j = tos32(0x080000000);
in 1: j = tos32(code(msg,msg_len-1) shl 24) | tos32(0x0800000);
in 2: j = tos32(code(msg,msg_len-2) shl 24) | (code(msg,msg_len-1) shl 16) | tos32(0x08000);
in 3: j = tos32(code(msg,msg_len-3) shl 24) | (code(msg,msg_len-2) shl 16) | (code(msg,msg_len-1) shl 8) | tos32(0x080);
end;

append(word_array,j);

while (len(word_array)%16 # 14) do
  append(word_array,0);
end;

ffffffff = tos32(0x0ffffffff);

append(word_array,shrr(msg_len,29));
append(word_array,(msg_len shl 3) & ffffffff);

bse = len(word_array);
for bs = 0 to bse-1 by 16 do
  for i = 0 to 15 do
    W[i] = word_array[bs+i];
  end;
  for i = 16 to 79 do
    W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
  end;
  A = H0;
  B = H1;
  C = H2;
  D = H3;
  E = H4;
  for i = 0 to 19 do
    temp = tos32(tou32(rotate_left(A,5)) + tou32((B&C) | (~B&D)) + tou32(E) + tou32(W[i]) + 0x5A827999) & ffffffff;
    E = D; D = C; C = rotate_left(B,30); B = A; A = temp;
  end;
  for i = 20 to 39 do
    temp = tos32(tou32(rotate_left(A,5)) + tou32(B^C^D) + tou32(E) + tou32(W[i]) + 0x6ED9EBA1) & ffffffff;
    E = D; D = C; C = rotate_left(B,30); B = A; A = temp;
  end;
  for i = 40 to 59 do
    temp = tos32(tou32(rotate_left(A,5)) + tou32((B&C) | (B&D) | (C&D)) + tou32(E) + tou32(W[i]) + 0x8F1BBCDC) & ffffffff;
    E = D; D = C; C = rotate_left(B,30); B = A; A = temp;
  end;
  for i = 60 to 79 do
    temp = tos32(tou32(rotate_left(A,5)) + tou32(B^C^D) + tou32(E) + tou32(W[i]) + 0xCA62C1D6) & ffffffff;
    E = D; D = C; C = rotate_left(B,30); B = A; A = temp;
  end;

  H0 = tos32(tou32(H0) + tou32(A)) & ffffffff;
  H1 = tos32(tou32(H1) + tou32(B)) & ffffffff;
  H2 = tos32(tou32(H2) + tou32(C)) & ffffffff;
  H3 = tos32(tou32(H3) + tou32(D)) & ffffffff;
  H4 = tos32(tou32(H4) + tou32(E)) & ffffffff;
end;
return cvt_hex(H0)+cvt_hex(H1)+cvt_hex(H2)+cvt_hex(H3)+cvt_hex(H4);
end;

function SHA1toStr(a) // Make the sha1 hash become real bytes
 r = '';
 while a # '' do
  r = r + char(hexnum(substr(a,0,2)));
  a = substr(a,2);
 end;
 return r;
end;
