// This is all the JavaScript code for the Sales Rank Express main page.


// LOCATION***********************

function setLocation()     {
  if (SREBeta.test(document.URL)) {
    host = "beta.salesrankexpress.com";
    style = "http://beta.salesrankexpress.com/SRE5.xsl";
    document.USForm.Host.value = host;
    document.CAForm.Host.value = host;
    document.UKForm.Host.value = host;
    document.FRForm.Host.value = host;
    document.DEForm.Host.value = host;
    document.JPForm.Host.value = host;
    document.USForm.Style.value = style;
    document.CAForm.Style.value = style;
    document.UKForm.Style.value = style;
    document.FRForm.Style.value = style;
    document.DEForm.Style.value = style;
    document.JPForm.Style.value = style;
  } 
}



// DISPLAY****************************

function showCountry()     {
  document.getElementById('USBlock').style.display='none';
  document.getElementById('CABlock').style.display='none';
  document.getElementById('UKBlock').style.display='none';
  document.getElementById('FRBlock').style.display='none';
  document.getElementById('DEBlock').style.display='none';
  document.getElementById('JPBlock').style.display='none';
  if (document.getElementById('CountryUS').checked) document.getElementById('USBlock').style.display='block';
  if (document.getElementById('CountryCA').checked) document.getElementById('CABlock').style.display='block';
  if (document.getElementById('CountryUK').checked) document.getElementById('UKBlock').style.display='block';
  if (document.getElementById('CountryFR').checked) document.getElementById('FRBlock').style.display='block';
  if (document.getElementById('CountryDE').checked) document.getElementById('DEBlock').style.display='block';
  if (document.getElementById('CountryJP').checked) document.getElementById('JPBlock').style.display='block';
}
function formatPrint()     {
  document.body.style.display='none';
  document.getElementById('Top').style.display='none';
  document.getElementById('Footer').style.display='none';
  document.getElementById('PrintButton').style.display='none';
  document.getElementById('UnprintButton').style.display='block';
  document.getElementById('Bottom').style.maxWidth='36em';
  document.getElementById('Bottom').style.borderTop='none';
  document.getElementById('HelpHead').style.pageBreakBefore='auto';
  document.body.style.display='block';
  window.location.hash='help';
}
function formatScreen()     {
  document.body.style.display='none';
  document.getElementById('Top').style.display='block';
  document.getElementById('Footer').style.display='block';
  document.getElementById('PrintButton').style.display='block';
  document.getElementById('UnprintButton').style.display='none';
  document.getElementById('Bottom').style.maxWidth='45em';
  document.getElementById('Bottom').style.borderTop='1px solid black';
  document.getElementById('HelpHead').style.pageBreakBefore='always';
  document.body.style.display='block';
  window.location.hash='help';
}



// FIELD COPYING***********************

function copyUSAuthor()     {
  document.CAForm.Author.value = document.USForm.Author.value;
  document.UKForm.Author.value = document.USForm.Author.value;
  document.FRForm.Author.value = document.USForm.Author.value;
  document.DEForm.Author.value = document.USForm.Author.value;
  document.JPForm.Author.value = document.USForm.Author.value;
}
function copyUSPublisher()     {
  document.CAForm.Publisher.value = document.USForm.Publisher.value;
  document.UKForm.Publisher.value = document.USForm.Publisher.value;
  document.FRForm.Publisher.value = document.USForm.Publisher.value;
  document.DEForm.Publisher.value = document.USForm.Publisher.value;
  document.JPForm.Publisher.value = document.USForm.Publisher.value;
}
function copyUSTitle()     {
  document.CAForm.Title.value = document.USForm.Title.value;
  document.UKForm.Title.value = document.USForm.Title.value;
  document.FRForm.Title.value = document.USForm.Title.value;
  document.DEForm.Title.value = document.USForm.Title.value;
  document.JPForm.Title.value = document.USForm.Title.value;
}
function copyUSKeywords()     {
  document.CAForm.Keywords.value = document.USForm.Keywords.value;
  document.UKForm.Keywords.value = document.USForm.Keywords.value;
  document.FRForm.Keywords.value = document.USForm.Keywords.value;
  document.DEForm.Keywords.value = document.USForm.Keywords.value;
  document.JPForm.Keywords.value = document.USForm.Keywords.value;
}
function copyUSAvailability()     {
  if (document.USForm.Availability.checked==true)     {
    document.CAForm.Availability.checked=true;
    document.UKForm.Availability.checked=true;
    document.FRForm.Availability.checked=true;
    document.DEForm.Availability.checked=true;
    document.JPForm.Availability.checked=true;
  }  else     {
    document.CAForm.Availability.checked=false;
    document.UKForm.Availability.checked=false;
    document.FRForm.Availability.checked=false;
    document.DEForm.Availability.checked=false;
    document.JPForm.Availability.checked=false;
  }  
}
function copyUS()     {
  copyUSAuthor();
  copyUSPublisher();
  copyUSTitle();
  copyUSKeywords();
  copyUSAvailability();
}
function copyCA()     {
  document.USForm.Author.value = document.CAForm.Author.value;
  document.USForm.Publisher.value = document.CAForm.Publisher.value;
  document.USForm.Title.value = document.CAForm.Title.value;
  document.USForm.Keywords.value = document.CAForm.Keywords.value;
}
function copyUK()     {
  document.USForm.Author.value = document.UKForm.Author.value;
  document.USForm.Publisher.value = document.UKForm.Publisher.value;
  document.USForm.Title.value = document.UKForm.Title.value;
  document.USForm.Keywords.value = document.UKForm.Keywords.value;
}
function copyFR()     {
  document.USForm.Author.value = document.FRForm.Author.value;
  document.USForm.Publisher.value = document.FRForm.Publisher.value;
  document.USForm.Title.value = document.FRForm.Title.value;
  document.USForm.Keywords.value = document.FRForm.Keywords.value;
}
function copyDE()     {
  document.USForm.Author.value = document.DEForm.Author.value;
  document.USForm.Publisher.value = document.DEForm.Publisher.value;
  document.USForm.Title.value = document.DEForm.Title.value;
  document.USForm.Keywords.value = document.DEForm.Keywords.value;
}
function copyJP()     {
  document.USForm.Author.value = document.JPForm.Author.value;
  document.USForm.Publisher.value = document.JPForm.Publisher.value;
  document.USForm.Title.value = document.JPForm.Title.value;
  document.USForm.Keywords.value = document.JPForm.Keywords.value;
}



// BUTTONS***************************

var submitted=false;

function handleSubmit()     {
  var isbn = document.USForm.Keywords.value;
  if (submitted == true) {
  submitted = false;
  return false;
  } else if (!(SRE.test(document.URL))) {
  return false;
  } else if ((document.USForm.Author.value == "") && (document.USForm.Publisher.value == "") && (document.USForm.Title.value == "") && (document.USForm.Keywords.value == ""))     {
  alert ("Hold on, there! You have to fill in at least one box!");
  return false;
  } else if ((document.USForm.Author.value !== "") && (document.USForm.Publisher.value !== "") && (document.USForm.Title.value !== "") && (document.USForm.Keywords.value !== "")) {
  alert("For best results, do NOT fill in all boxes. Enter only as much as you need to identify a book or books. Tip: A valid ISBN is enough by itself!");
  return false;
  } else  if (isbn == "") {
  submitted = true;
  return true;
  } else if (isbn.indexOf("-") !== -1) {
  alert("Amazon does not like hyphens in ISBNs. Please leave them out!");
  return false;
  } else if (isbn.indexOf("*") !== -1) {
  submitted = true;
  return true;
  } else if ((isbn.length != 10) && (isbn.length != 13)) {
  alert("An ISBN must be 10 or 13 numerals. An ASIN must be 10 letters and/or numerals. Please try again."); 
  return false;
  } else if ((isbn.length == 13) && (isbn.indexOf("978") !== 0) && (isbn.indexOf("979") !== 0)) {
  alert("A 13-digit ISBN must start with 978 or 979. Please try again."); 
  return false;
  } else      {
  submitted = true;
  return true;
  }
}
function clearForm()     {
  document.USForm.Author.value="";
  document.USForm.Publisher.value="";
  document.USForm.Title.value="";
  document.USForm.Keywords.value="";
  document.USForm.Availability.checked=false;
  copyUS();
}
function save1()     {
  document.X1Form.Author.value = document.USForm.Author.value;
  document.X1Form.Publisher.value = document.USForm.Publisher.value;
  document.X1Form.Title.value = document.USForm.Title.value;
  document.X1Form.Keywords.value = document.USForm.Keywords.value;
  if (document.USForm.Availability.checked==true)     {
    document.X1Form.Availability.checked=true;
    }  else     {
    document.X1Form.Availability.checked=false;
    }
}
function save2()     {
  document.X2Form.Author.value = document.USForm.Author.value;
  document.X2Form.Publisher.value = document.USForm.Publisher.value;
  document.X2Form.Title.value = document.USForm.Title.value;
  document.X2Form.Keywords.value = document.USForm.Keywords.value;
  if (document.USForm.Availability.checked==true)     {
    document.X2Form.Availability.checked=true;
    }  else     {
    document.X2Form.Availability.checked=false;
    }
}
function recall1()     {
  document.USForm.Author.value = document.X1Form.Author.value;
  document.USForm.Publisher.value = document.X1Form.Publisher.value;
  document.USForm.Title.value = document.X1Form.Title.value;
  document.USForm.Keywords.value = document.X1Form.Keywords.value;
  if (document.X1Form.Availability.checked==true)     {
    document.USForm.Availability.checked=true;
    }  else     {
    document.USForm.Availability.checked=false;
    }
  copyUS();
}
function recall2()     {
  document.USForm.Author.value = document.X2Form.Author.value;
  document.USForm.Publisher.value = document.X2Form.Publisher.value;
  document.USForm.Title.value = document.X2Form.Title.value;
  document.USForm.Keywords.value = document.X2Form.Keywords.value;
  if (document.X2Form.Availability.checked==true)     {
    document.USForm.Availability.checked=true;
    }  else     {
    document.USForm.Availability.checked=false;
    }
  copyUS();
}

var Kindle=true;

function recallAaron()     {
  if (Kindle == true) {
  Kindle = false;
  document.USForm.Author.value="";
  document.USForm.Publisher.value="";
  document.USForm.Title.value="";
  document.USForm.Keywords.value="9780938497*";
  document.USForm.Availability.checked=false;
  copyUS();
  document.USForm.Power.value="binding:paperback and not mass";
  document.CAForm.Power.value="binding:paperback and not mass";
  document.UKForm.Power.value="binding:paperback and not mass";
  document.FRForm.Power.value="binding:broche";
  document.DEForm.Power.value="binding:taschenbuch";
  document.JPForm.Power.value="binding:ペーパーバック";
  document.USForm.Sort.value="salesrank";
  document.CAForm.Sort.value="salesrank";
  document.UKForm.Sort.value="salesrank";
  document.FRForm.Sort.value="salesrank";
  document.DEForm.Sort.value="salesrank";
  document.JPForm.Sort.value="salesrank";
  document.getElementById('FRSearchIndex2').checked=true;
  document.getElementById('DESearchIndex2').checked=true;
  document.getElementById('JPSearchIndex2').checked=true;
  } else {
  Kindle = true;
  document.USForm.Author.value="";
  document.USForm.Publisher.value="Shepard Publications";
  document.USForm.Title.value="";
  document.USForm.Keywords.value="";
  document.USForm.Availability.checked=false;
  copyUS();
  document.USForm.Power.value="binding:kindle";
  document.CAForm.Power.value="binding:paperback and not mass";
  document.UKForm.Power.value="binding:paperback and not mass";
  document.FRForm.Power.value="binding:broche";
  document.DEForm.Power.value="binding:taschenbuch";
  document.JPForm.Power.value="binding:ペーパーバック";
  document.USForm.Sort.value="salesrank";
  document.CAForm.Sort.value="salesrank";
  document.UKForm.Sort.value="salesrank";
  document.FRForm.Sort.value="salesrank";
  document.DEForm.Sort.value="salesrank";
  document.JPForm.Sort.value="salesrank";
  document.getElementById('FRSearchIndex2').checked=true;
  document.getElementById('DESearchIndex2').checked=true;
  document.getElementById('JPSearchIndex2').checked=true;
  }
}


// COOKIES****************************

function setCookies()     {
  writeString(MyCookieObj,document.CountryForm,'WAFC_index_CountryForm', 45);
  writeString(MyCookieObj,document.USForm,'WAFC_index_USForm', 45);
  writeStringParts(MyCookieObj,document.CAForm,'WAFC_index_CAForm', 45);
  writeStringParts(MyCookieObj,document.UKForm,'WAFC_index_UKForm', 45);
  writeStringParts(MyCookieObj,document.FRForm,'WAFC_index_FRForm', 45);
  writeStringParts(MyCookieObj,document.DEForm,'WAFC_index_DEForm', 45);
  writeStringParts(MyCookieObj,document.JPForm,'WAFC_index_JPForm', 45);
  writeString(MyCookieObj,document.X1Form,'WAFC_index_X1Form', 45);
  writeString(MyCookieObj,document.X2Form,'WAFC_index_X2Form', 45);
}
function readCookies()     {
  readString(MyCookieObj,document.CountryForm,'WAFC_index_CountryForm'); 
  readString(MyCookieObj,document.USForm,'WAFC_index_USForm');
  readString(MyCookieObj,document.CAForm,'WAFC_index_CAForm');
  readString(MyCookieObj,document.UKForm,'WAFC_index_UKForm');
  readString(MyCookieObj,document.FRForm,'WAFC_index_FRForm');
  readString(MyCookieObj,document.DEForm,'WAFC_index_DEForm');
  readString(MyCookieObj,document.JPForm,'WAFC_index_JPForm');
  readString(MyCookieObj,document.X1Form,'WAFC_index_X1Form');
  readString(MyCookieObj,document.X2Form,'WAFC_index_X2Form');
}

// The remaining code is from WebAssist's Cookies Toolkit 3.1.0 generated file Cookies.js but with changes to limit the fields processed. Also, the escape and unescape functions are replaced with encodeURIComponent and decodeURIComponent to properly handle Unicode.

function CookieDef(expires,path,domain,secure)
{
  this.secure = secure;
  this.path = path;
  this.domain = domain;
  this.getValue = getCookie;
  this.setValue = setCookie;
  this.expire = deleteCookie;
  if (expires == 0) {
    this.expires = "";
  } else {
    var today_date = new Date();
	 var expire_seconds = today_date.getTime() + (expires * 24 * 60 * 60  * 1000);
    today_date.setTime(expire_seconds);
    this.expires = today_date.toGMTString();
  }
}
function getCV(offset) {
  var endstr = document.cookie.indexOf(";", offset);
  if (endstr == -1) endstr = document.cookie.length;
  return decodeURIComponent(document.cookie.substring(offset, endstr)).replace(/\+/g," ");
}
function getCookie(name) {
  var arg = name.toUpperCase() + "=";
  var arg2 = name.replace(/_/g,"%5F").toUpperCase() + "=";
  var alen = arg.length;
  var alen2 = arg2.length;
  var clen = document.cookie.length;
  var i = 0;
  while (i < clen) {
    var j = i + alen;
    var j2 = i + alen2;
    if (document.cookie.substring(i, j).toUpperCase() == arg)
      return getCV(j);
    if (document.cookie.substring(i, j2).toUpperCase() == arg2)
      return getCV(j2);
    i = document.cookie.indexOf(" ", i) + 1;
    if (i == 0) break;
  }
  return "";
}
function setCookie(name,value)
{
  document.cookie = name.toUpperCase() + "=" + encodeURIComponent(value) +
    ((this.expires == "") ? "" : ("; expires=" + this.expires)) +
    ((this.path == "") ? "" : ("; path=" + this.path)) +
    ((this.domain == "") ? "" : ("; domain=" + this.domain)) +
    ((this.secure == true) ? "; secure" : "");
}
function deleteCookie(name) {
  document.cookie = name + "=" + "" + "; expires=Thu,01-Jan-70 00:00:01 GMT";
}
function getID(formElement, x)  {
  var retID = String(x);
  if (formElement.id) {
	  retID = String(formElement.id);
  }
  else if (formElement.name)  {
	  retID = String(formElement.name);
  }
  return retID;
}

//writeString writes all fields except hidden

function writeString(cookieobj,theForm,SaveAs)  {
  var theFormElements = theForm.elements;
  var theCookieString = "";
  var theCookieSeparator = "|?";
  for (var x=0; x<theFormElements.length; x++)  {
    if (theFormElements[x].tagName=="TEXTAREA")  {
      if (theCookieString!="")  {
	    theCookieString += theCookieSeparator;
	  }
	  theCookieString += getID(theFormElements[x],x) + "=" + theFormElements[x].value;
    }
	else if (theFormElements[x].tagName=="SELECT")  {
      if (theCookieString != "")  {
	    theCookieString += theCookieSeparator;
	  }
	  for (var y=0; y<theFormElements[x].options.length; y++)  {
	    if (theFormElements[x].options[y].selected) {
	      theCookieString += getID(theFormElements[x],x) + "=" + theFormElements[x].options[y].value;
		}
	  }
    }
	else  {
	  theType = "text";
	  if (theFormElements[x].type) {
	    theType = theFormElements[x].type.toLowerCase();
	  }
	  if (theType == "text")  {
        if (theCookieString!="")  {
	      theCookieString += theCookieSeparator;
	    }
	    theCookieString += getID(theFormElements[x],x) + "=" + theFormElements[x].value;
	  }
	  if (theType == "checkbox")  {
	    if (theFormElements[x].checked)  {
          if (theCookieString!="")  {
	        theCookieString += theCookieSeparator;
	      }
	      theCookieString += getID(theFormElements[x],x) + "=" + theFormElements[x].value;
		}
	  }
	  if (theType == "radio")  {
	    if (theFormElements[x].checked)  {
          if (theCookieString!="")  {
	        theCookieString += theCookieSeparator;
	      }
	      theCookieString += getID(theFormElements[x],x) + "=" + theFormElements[x].value;
		}
	  }
    }
  }
  cookieobj.setValue(SaveAs, theCookieString);
}


//writeStringParts writes only select and radio

function writeStringParts(cookieobj,theForm,SaveAs)  {
  var theFormElements = theForm.elements;
  var theCookieString = "";
  var theCookieSeparator = "|?";
  for (var x=0; x<theFormElements.length; x++)  {
    if (theFormElements[x].tagName=="SELECT")  {
      if (theCookieString != "")  {
	    theCookieString += theCookieSeparator;
	  }
	  for (var y=0; y<theFormElements[x].options.length; y++)  {
	    if (theFormElements[x].options[y].selected) {
	      theCookieString += getID(theFormElements[x],x) + "=" + theFormElements[x].options[y].value;
		}
	  }
    }
	else  {
	  theType = "text";
	  if (theFormElements[x].type) {
	    theType = theFormElements[x].type.toLowerCase();
	  }
	  if (theType == "radio")  {
	    if (theFormElements[x].checked)  {
          if (theCookieString!="")  {
	        theCookieString += theCookieSeparator;
	      }
	      theCookieString += getID(theFormElements[x],x) + "=" + theFormElements[x].value;
		}
	  }
    }
  }
  cookieobj.setValue(SaveAs, theCookieString);
}


function findValInString(theString,theVal,theSep)  {
  var retVal = "";
  var searchStr = theSep + theString + theSep;
  var findStr = theSep + theVal + "=";
  if (searchStr.indexOf(findStr) >= 0)  {
    retVal = searchStr.substring(searchStr.indexOf(findStr)+findStr.length);
	retVal = retVal.substring(0,retVal.indexOf(theSep));
  }
  return retVal;
}

function findMatchInString(theString,theMatch,theSep)  {
  var searchStr = theSep + theString + theSep;
  var findStr = theSep + theMatch + theSep;
  if (searchStr.indexOf(findStr) >= 0)  {
    return true;
  }
  return false;
}


function readString(cookieobj,theForm,SaveAs)  {
  var cookieVal = cookieobj.getValue(SaveAs);
  var theFormElements = theForm.elements;
  var theCookieSeparator = "|?";
  for (var x=0; x<theFormElements.length; x++)  {
    if (theFormElements[x].tagName=="TEXTAREA")  {
	  var findID = getID(theFormElements[x], x);
	  var findVal = findValInString(cookieVal,findID,theCookieSeparator);
	  if (findVal != "")  {
	    theFormElements[x].value = findVal;
	  }
    }
	else if (theFormElements[x].tagName=="SELECT")  {
	  var findID = getID(theFormElements[x], x);
	  for (var y=0; y<theFormElements[x].options.length; y++)  {
        if (findMatchInString(cookieVal,findID+"="+theFormElements[x].options[y].value,theCookieSeparator))  {
		  theFormElements[x].options[y].selected = true;
		}
	  }
    }
	else  {
	  theType = "text";
	  if (theFormElements[x].type) {
	    theType = theFormElements[x].type.toLowerCase();
	  }
	  if (theType == "text")  {
        var findID = getID(theFormElements[x], x);
	    var findVal = findValInString(cookieVal,findID,theCookieSeparator);
	    if (findVal != "")  {
	      theFormElements[x].value = findVal;
	    }
	  }
	  if (theType == "checkbox")  {
	    var findID = getID(theFormElements[x], x);
        if (findMatchInString(cookieVal,findID+"="+theFormElements[x].value,theCookieSeparator))  {
		  theFormElements[x].checked = true;
		}
	  }
	  if (theType == "radio")  {
        var findID = getID(theFormElements[x], x);
        if (findMatchInString(cookieVal,findID+"="+theFormElements[x].value,theCookieSeparator))  {
		  theFormElements[x].checked = true;
		}
	  }
    }
  }
}

function daysToExpire(expiresDays)  {
  var today_date = new Date();
  var expire_seconds = today_date.getTime() + (expiresDays * 24 * 60 * 60  * 1000);
  today_date.setTime(expire_seconds);
  return today_date.toGMTString();
}

MyCookieObj = new CookieDef(30,"/","","0");

SRE=/salesrankexpress.com/i;
SREBeta=/beta.salesrankexpress.com/i;



// AUTHENTICATION****************************

// The following code is taken from four original files: SREAWSSign.js by fractalnavel, AWSQuerySigner.js by fractalnavel, ecmanaut.base64.js by ecmanaut, and jssha256.js by B. Poettering. ALL THIS CODE CAN BE REMOVED IF A PERL AUTHENTICATION SOLUTION IS ADOPTED.



//SREAWSSign.js**************

var strAWSSecretAccessKey = "7DRWjwRmD6S9VQG3e6eEVjPCQSRyqgNK6l8gT4CA";

function SREAWSSign( theForm, bOkToSubmit ) {
	if ( bOkToSubmit )
		AWSQS.signForm( theForm, strAWSSecretAccessKey );
	return bOkToSubmit;
}

var W1252 = (function() {

	var aHex = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];

	function encode( str ) {
		var strEncoded = "";
		for ( var i = 0; i < str.length; i++ ) {
			var nChar = str.charCodeAt( i );
			if ( nChar > 127 )
				strEncoded += "%" + aHex[ nChar >> 4 ] + aHex[ nChar & 15 ];
			else
				strEncoded += str.charAt( i );
		}
		return strEncoded;
	}

	return { encodeString: encode };
})();


//AWSQuerySigner.js**************

var AWSQS = (function() {

	function array_to_string( ary ) {
		var str = "";
		for( var i = 0; i < ary.length; i++ ) {
			str += String.fromCharCode( ary[i] );
		}
		return str;
	}

	function local_HMAC_SHA256_MAC( strKey, strMsg ) {
	  HMAC_SHA256_init( strKey );
	  HMAC_SHA256_write( strMsg );
	  var aHash = HMAC_SHA256_finalize();
	  return array_to_string( aHash );
	}

	function fnTranslate( str, aTranslate ) {
		for ( var i = 0; i < aTranslate.length; i++ ) {
			str = str.replace( aTranslate[i][0], aTranslate[i][1] );
		}
		return str;
	}

	function encodeURIComponentAWS( str ) {
		return fnTranslate( encodeURIComponent( str ),
			[ [/!/g, "%21"], [/'/g, "%27"], [/\(/g, "%28"], [/\)/g, "%29"], [/\*/g, "%2A"] ] );
	}

	function toZString( dt ) {
		return dt.toUTCString().replace( /.{3}, (\d{1,2}) .{3} (\d{4}) (\d{2}:\d{2}:\d{2}) .{3}/,
			function(strMatch, strDay, strYear, strTime) {
				var strDate = (dt.getUTCDate()).toString().replace( /^(\d)$/, "0$1" );
				var strMonth = (dt.getUTCMonth()+1).toString().replace( /^(\d)$/, "0$1" );
				return strYear + "-" + strMonth + "-" + strDate + "T" + strTime + "Z";
			});
	}

	function timestamp() { return toZString( new Date() ); }

	function fnSignature( strMethod, strQuery, strKey ) {
		var bEncode = strMethod == "GET";

		var strTimestamp = timestamp();
		strQuery += "&Timestamp=" + ( bEncode ? strTimestamp : encodeURIComponentAWS( strTimestamp ) );

		var strToSign = strQuery.replace( /(https?:\/\/)([^\/]*)(\/.*)\?(.*)/i,
			function( strMatch, strScheme, strHost, strUri, strParams ) {
				var aParams = strParams.split("&").sort();
					if ( bEncode ) {
						for ( var i = 0; i < aParams.length; i++ ) {
							var aKV = aParams[i].split("=");
							for ( var j = 0; j < aKV.length; j++ ) {
								aKV[j] = encodeURIComponentAWS( aKV[j] );
							}
							aParams[i] = aKV.join("=");
						}
					}
				strParams = aParams.join("&");
				strHost = strHost.toLowerCase();
				return ([ strMethod, strHost, strUri, strParams ]).join("\n");
			});

		var strSignature = Base64.encode( local_HMAC_SHA256_MAC( strKey, strToSign ) );
		if ( bEncode ) {
			strSignature = encodeURIComponentAWS( strSignature );
		}

		return { Timestamp: strTimestamp, Signature: strSignature };
	}

	function encodeKV( strKey, strVal )  {
		var strK = encodeURIComponentAWS( strKey );
		var strV = encodeURIComponentAWS( strVal );
		return strK + "=" + strV;
	}

	function getKV( elem )  {
		return encodeKV( elem.name, elem.value );
	}

	function getQuery( oForm )  {
		var aQuery = [];

		var colElements = oForm.elements;
		for ( var i = 0; i < colElements.length; i++ )  {
			var elem = colElements[i];
			var strType = elem.type ? elem.type.toLowerCase() : "";
			var strTag = elem.tagName.toLowerCase();

			switch( true ) {

				case elem.name == "Signature":
				case elem.name == "Timestamp":
					// SKIP!
					break;

				case strType == "hidden":
				case strType == "text":
				case strType == "checkbox" && elem.checked:
				case strType == "radio" && elem.checked:
				case strTag == "textarea":

					aQuery.push( getKV( elem ) );
					break;

				case strTag == "select":
					var bDone = false;
					for ( var j = 0; j < elem.options.length; j++ ) {
						if ( !bDone && elem.options[j].selected ) {
							aQuery.push( encodeKV( elem.name, elem.options[j].value ) );
							bDone = true;
						}
					}
					if ( !bDone ) {
						aQuery.push( encodeKV( elem.name, "" ) );
					}
					break;

				default:
			}
		}
		return oForm.action + "?" + aQuery.join("&");
	}

	function setHidden( oForm, strName, strValue ) {
		var elem = oForm.elements[ strName ];
		if ( !elem ) {
			elem = document.createElement("input");
			elem.type = "hidden";
			elem.name = strName;
			oForm.appendChild(elem);
		}
		elem.value = strValue;
	}

	function fnFormSignature( oForm, strKey ) {
		return fnSignature( oForm.method.toUpperCase(), getQuery( oForm ), strKey );
	}

	function fnQuerySignature( strQuery, strKey ) {
		return fnSignature( "GET", strQuery, strKey );
	}

	function fnSignForm( oForm, strKey ) {
		var oSign = fnFormSignature( oForm, strKey );
		setHidden( oForm, "Timestamp", oSign.Timestamp );
		setHidden( oForm, "Signature", oSign.Signature );
	}

	// sign query with key: add signature & timestamp
	function fnSignQuery( strQuery, strKey ) {
		var oSign = fnQuerySignature( strQuery, strKey );
		return strQuery + "&Timestamp=" + oSign.Timestamp + "&Signature=" + oSign.Signature;
	}

	return {
				signForm: fnSignForm,
				signQuery: fnSignQuery,
				getFormSignature: fnFormSignature,
				getQuerySignature: fnQuerySignature,
				getSignature: fnSignature
			};
})();



//ecmanaut.base64.js**************

var Base64 = (function() {
  function encode_base64(data) {
    var out = "", c1, c2, c3, e1, e2, e3, e4;
    for (var i = 0; i < data.length; ) {
       c1 = data.charCodeAt(i++);
       c2 = data.charCodeAt(i++);
       c3 = data.charCodeAt(i++);
       e1 = c1 >> 2;
       e2 = ((c1 & 3) << 4) + (c2 >> 4);
       e3 = ((c2 & 15) << 2) + (c3 >> 6);
       e4 = c3 & 63;
       if (isNaN(c2))
         e3 = e4 = 64;
       else if (isNaN(c3))
         e4 = 64;
       out += tab.charAt(e1) + tab.charAt(e2) + tab.charAt(e3) + tab.charAt(e4);
    }
    return out;
  }

  function decode_base64(data) {
    var out = "", c1, c2, c3, e1, e2, e3, e4;
    for (var i = 0; i < data.length; ) {
      e1 = tab.indexOf(data.charAt(i++));
      e2 = tab.indexOf(data.charAt(i++));
      e3 = tab.indexOf(data.charAt(i++));
      e4 = tab.indexOf(data.charAt(i++));
      c1 = (e1 << 2) + (e2 >> 4);
      c2 = ((e2 & 15) << 4) + (e3 >> 2);
      c3 = ((e3 & 3) << 6) + e4;
      out += String.fromCharCode(c1);
      if (e3 != 64)
        out += String.fromCharCode(c2);
      if (e4 != 64)
        out += String.fromCharCode(c3);
    }
    return out;
  }

  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  return { encode:encode_base64, decode:decode_base64 };
})();



//jssha256.js**************

function string_to_array(str) {
  var len = str.length;
  var res = new Array(len);
  for(var i = 0; i < len; i++)
    res[i] = str.charCodeAt(i);
  return res;
}

function array_to_hex_string(ary) {
  var res = "";
  for(var i = 0; i < ary.length; i++)
    res += SHA256_hexchars[ary[i] >> 4] + SHA256_hexchars[ary[i] & 0x0f];
  return res;
}

function SHA256_init() {
  SHA256_H = new Array(0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19);
  SHA256_buf = new Array();
  SHA256_len = 0;
}

function SHA256_write(msg) {
  if (typeof(msg) == "string")
    SHA256_buf = SHA256_buf.concat(string_to_array(msg));
  else
    SHA256_buf = SHA256_buf.concat(msg);
  for(var i = 0; i + 64 <= SHA256_buf.length; i += 64)
    SHA256_Hash_Byte_Block(SHA256_H, SHA256_buf.slice(i, i + 64));
  SHA256_buf = SHA256_buf.slice(i);
  SHA256_len += msg.length;
}

function SHA256_finalize() {
  SHA256_buf[SHA256_buf.length] = 0x80;

  if (SHA256_buf.length > 64 - 8) {
    for(var i = SHA256_buf.length; i < 64; i++)
      SHA256_buf[i] = 0;
    SHA256_Hash_Byte_Block(SHA256_H, SHA256_buf);
    SHA256_buf.length = 0;
  }

  for(var i = SHA256_buf.length; i < 64 - 5; i++)
    SHA256_buf[i] = 0;
  SHA256_buf[59] = (SHA256_len >>> 29) & 0xff;
  SHA256_buf[60] = (SHA256_len >>> 21) & 0xff;
  SHA256_buf[61] = (SHA256_len >>> 13) & 0xff;
  SHA256_buf[62] = (SHA256_len >>> 5) & 0xff;
  SHA256_buf[63] = (SHA256_len << 3) & 0xff;
  SHA256_Hash_Byte_Block(SHA256_H, SHA256_buf);

  var res = new Array(32);
  for(var i = 0; i < 8; i++) {
    res[4 * i + 0] = SHA256_H[i] >>> 24;
    res[4 * i + 1] = (SHA256_H[i] >> 16) & 0xff;
    res[4 * i + 2] = (SHA256_H[i] >> 8) & 0xff;
    res[4 * i + 3] = SHA256_H[i] & 0xff;
  }

  delete SHA256_H;
  delete SHA256_buf;
  delete SHA256_len;
  return res;
}

function SHA256_hash(msg) {
  var res;
  SHA256_init();
  SHA256_write(msg);
  res = SHA256_finalize();
  return array_to_hex_string(res);
}

function HMAC_SHA256_init(key) {
  if (typeof(key) == "string")
    HMAC_SHA256_key = string_to_array(key);
  else
    HMAC_SHA256_key = new Array().concat(key);

  if (HMAC_SHA256_key.length > 64) {
    SHA256_init();
    SHA256_write(HMAC_SHA256_key);
    HMAC_SHA256_key = SHA256_finalize();
  }

  for(var i = HMAC_SHA256_key.length; i < 64; i++)
    HMAC_SHA256_key[i] = 0;
  for(var i = 0; i < 64; i++)
    HMAC_SHA256_key[i] ^=  0x36;
  SHA256_init();
  SHA256_write(HMAC_SHA256_key);
}

function HMAC_SHA256_write(msg) {
  SHA256_write(msg);
}

function HMAC_SHA256_finalize() {
  var md = SHA256_finalize();
  for(var i = 0; i < 64; i++)
    HMAC_SHA256_key[i] ^= 0x36 ^ 0x5c;
  SHA256_init();
  SHA256_write(HMAC_SHA256_key);
  SHA256_write(md);
  for(var i = 0; i < 64; i++)
    HMAC_SHA256_key[i] = 0;
  delete HMAC_SHA256_key;
  return SHA256_finalize();
}

function HMAC_SHA256_MAC(key, msg) {
  var res;
  HMAC_SHA256_init(key);
  HMAC_SHA256_write(msg);
  res = HMAC_SHA256_finalize();
  return array_to_hex_string(res);
}

SHA256_hexchars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  'a', 'b', 'c', 'd', 'e', 'f');

SHA256_K = new Array(
  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
  0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
  0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
  0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
  0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
  0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
);

function SHA256_sigma0(x) {
  return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
}

function SHA256_sigma1(x) {
  return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
}

function SHA256_Sigma0(x) {
  return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^
    ((x >>> 22) | (x << 10));
}

function SHA256_Sigma1(x) {
  return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^
    ((x >>> 25) | (x << 7));
}

function SHA256_Ch(x, y, z) {
  return z ^ (x & (y ^ z));
}

function SHA256_Maj(x, y, z) {
  return (x & y) ^ (z & (x ^ y));
}

function SHA256_Hash_Word_Block(H, W) {
  for(var i = 16; i < 64; i++)
    W[i] = (SHA256_sigma1(W[i - 2]) +  W[i - 7] +
      SHA256_sigma0(W[i - 15]) + W[i - 16]) & 0xffffffff;
  var state = new Array().concat(H);
  for(var i = 0; i < 64; i++) {
    var T1 = state[7] + SHA256_Sigma1(state[4]) +
      SHA256_Ch(state[4], state[5], state[6]) + SHA256_K[i] + W[i];
    var T2 = SHA256_Sigma0(state[0]) + SHA256_Maj(state[0], state[1], state[2]);
    state.pop();
    state.unshift((T1 + T2) & 0xffffffff);
    state[4] = (state[4] + T1) & 0xffffffff;
  }
  for(var i = 0; i < 8; i++)
    H[i] = (H[i] + state[i]) & 0xffffffff;
}

function SHA256_Hash_Byte_Block(H, w) {
  var W = new Array(16);
  for(var i = 0; i < 16; i++)
    W[i] = w[4 * i + 0] << 24 | w[4 * i + 1] << 16 |
      w[4 * i + 2] << 8 | w[4 * i + 3];
  SHA256_Hash_Word_Block(H, W);
}




