This repository has been archived on 2021-12-10. You can view files and clone it, but cannot push or open issues or pull requests.
D3/D3-Annotator/auto_store.js

890 lines
30 KiB
JavaScript

/* Licence: Mozilla Public License Version 2.0
* Icons: Book by Mike Rowe from the Noun Project,
* Justice by Creative Stall from the Noun Project
* Author: Jesper Bergman (jesperbe@dsv.su.se)
*/
/* Start by importing functions */
//import {getCategoryFromDatabase} from './popup/add_category.js';
export {modifyDatabaseEntry, saveHighlightedText, setHighlightedText, syncWithServer, syncCategories};
/*
* Some silly variables for window dressing etc.
*/
var myWindowId;
var currentTab = [];
const contentBox = document.querySelector("#content");
const cryptoObject = window.crypto.subtle;
const encoder = new TextEncoder();
//const data = encoder.encode("loremipsum");
//const hash = cryptoObject.digest("SHA-256", data).then(onSuccess,onError);
/* Global variables */
var currentlyHighlightedText;
var annotatorUUID;
var uuid;
var onionSitesOnly = true;
var saveWebpagesToPDF = false;
/*
Press S - store text to file. How to deal with this in the future? Redo action?
*/
window.addEventListener("keydown", function(event){
if(event.code == "KeyS"){
var ht = setHighlightedText("get");
console.log("key event listener + S ", ht);
}
/*if(event.code =="ControlLeft"){
console.log("Control left pressed.");
}*/
});
async function modifyDatabaseEntry(command, argument){
var curl = await browser.tabs.query({lastFocusedWindow: false, highlighted:true}).then((tabs) => extractURL(tabs));
console.log("curl:", curl);
if(curl == "undefined"){ // Without quotation marks?
console.log("URL undefined. Should cancel everything here.");
}
var objectHashsum = await calculateHashsum(curl);
var dbObject = await browser.storage.local.get(objectHashsum).then(gotItem, onError);
console.log("Command: ", command, "; DB object to modify is: ", dbObject, " ; Hash sum is: ", objectHashsum, "; Type is: ", typeof(objectHashsum), "; Requested command is to do something with: ", argument);
/* Insert a try-catch statement, so that one cannot annotate non-existing URLs, like non-onion sites. */
switch(command){
case "category":
dbObject[objectHashsum].category = argument;
console.log("|-- Adding category: ", argument);
browser.storage.local.set(dbObject).then(setItem(), onError);
syncWithServer("category", dbObject);
break;
case "annotation":
//argument+= ";REF-HT;" + currentlyHighlightedText; //+ dbObject[objectHashsum].text.length;
dbObject[objectHashsum].notes.push(argument);
browser.storage.local.set(dbObject).then(setItem(), onError);
console.log("|-- Annotation: ", argument, " saved to local.storage DB.");
syncWithServer("annotation",dbObject);
break;
}
return true;
}
/*
* Marked text should be saved as array elements in order to allow for more than one excerpt.
* */
async function saveHighlightedText(highlightedText){
var hiArray = [];
var tabs = await browser.tabs.query({currentWindow: true, active: true}).then(gotItem, onError);
var url = tabs[0].url;
var objectHashsum = await calculateHashsum(url);
var dbObject = await browser.storage.local.get(objectHashsum).then(gotItem, onError);
hiArray = dbObject[objectHashsum].text;
hiArray.push(highlightedText);
dbObject[objectHashsum].text = hiArray;
browser.storage.local.set(dbObject).then(setItem(), onError);
console.log("|-- Added ", url, " and ", highlightedText, " to local.storage");
currentlyHighlightedText = highlightedText;
/* Save selection to local.storage */
setHighlightedText(highlightedText);
/* Sync */
syncWithServer("webpage",dbObject);
}
/* Get the last accessed tab. */
function extractURL(tabbar){
var tabs = tabbar;
var lastAccess = 0;
var tabId = 0;
for(var i=0; i<tabs.length;i++){
if(tabs[i].lastAccessed > lastAccess){
if(tabs[i].url.slice(0,6).includes("about:") == false){
lastAccess = tabs[i].lastAccessed;
tabId = i;
}
}
}
var url = tabs[tabId].url;
tabId=0;
return url;
}
async function gettingAllData(url){
let hash = await calculateHashsum(url);
return hash;
}
async function calculateHashsum(raw){
//let encoder = new TextEncoder();
//let hash = await window.crypto.subtle.digest("SHA-256", encoder.encode(raw)).then(onSuccess, onError);
let hash = SHA256(raw);
console.log("Calculated hash in calculateHashsum() is: ", hash, "and RAW: ", raw);
return hash;
}
// Automatically add URLs, timestamp, etc. to local.storage
async function addToDatabase(tabs){
var webpage = {};
let tabURL = tabs[0].url;
let domainURL = "unconventional";
let dateObject = new Date();
let cettimestamp = dateObject.getTime();
let webpageChecksum = new Request(tabURL);
webpageChecksum = webpageChecksum.integrity;
let categoryName = "N/A";
let md5sum = hex_md5(tabURL);
// Get domain and use it as an umbrella
domainURL = getDomain(tabURL);
var str = tabURL.slice(0,6);
if(onionSitesOnly == true && domainURL.includes(".onion")){
// Exclude internal URLs like about:config
if(str.includes("about:") == false && str.includes("moz-ex") == false){
let hash = await calculateHashsum(tabURL); //(await window.crypto.subtle.digest("SHA-256", data).then(onSuccess, onError));
// Create array to store in loca.storage DB
let arr = {url: tabURL, domain: domainURL, category: categoryName, sha256: hash, timestamp: cettimestamp, checksum: webpageChecksum, md5: md5sum,text: [], notes: []};
// Use URL SHA256 as key and above array as the values for it. First check if entry exists
webpage[hash]= arr;
let occupiedEntry = await browser.storage.local.get(hash).then(gotItem, onError);
console.log("Checking existing DB entry for this webpage: ", occupiedEntry[hash]," -- and checksum: ", webpageChecksum, md5sum);
if(occupiedEntry[hash] == undefined){
console.log("Webpage does not exist yet. Adding it. ", savePage(tabURL));
/* Add to FF local.storage */
browser.storage.local.set(webpage).then(setItem, onError);
/* Send to central storage server */
syncWithServer("webpage", webpage);
}
/*else if(occupiedEntry[hash].category != "N/A"){
console.log("Looking at N/A category for this one. Let us assign a category for it.");
browser.storage.local.set(webpage).then(setItem, onError);
}*/
else{
console.log("Wepage already exists. Not touching anything. Exit.");
}
}
}
}
function savePage(url){
fetch(url, {mode:'no-cors'}).then(function(response){
console.log("fetch :: ", response.text());
return response.text();
}).catch(function(err) {
console.log('Failed to fetch page: ', err);
});
}
/* Synchronise categories with remote database server. */
async function syncCategories(){
let xhr_ = new XMLHttpRequest();
let urlQuery = 'http://10.1.100.17:8080/api/categories';
xhr_.open("GET", urlQuery);
var s_categories = "";
/* Send the proper header information along with the request */
xhr_.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr_.onreadystatechange = function(){
if (this.readyState === XMLHttpRequest.DONE && this.status === 200){
s_categories = xhr_.response;
let obj = JSON.parse(s_categories);
let cat_arr = [];
for(let i=0; i < obj.length; i++){
// getCategoryFromDatabase(obj[i].category);
cat_arr.push(obj[i].category);
}
let cat_insert = {category: cat_arr};
console.log("|------ cat_insert: ", typeof(cat_insert), cat_insert);
browser.storage.local.set(cat_insert).then(function(){console.log("Added new categories from server sync.", cat_arr)});
}
}
xhr_.send();
}
/* Synchronise with remote database server. */
async function syncWithServer(itemType, itemObject){
let itemJSON = "";
var xhr = new XMLHttpRequest();
let urlQuery = 'http://10.1.100.17:8080/api/command?uuid=ndmdiHk8'; //+ uuid.annotatorUUID; //08puj3X
xhr.open("POST", urlQuery);
let t2 = null;
let t1 = performance.now();
let sent_hashsum = "";
let received_hashsum ="";
/* Send the proper header information along with the request */
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr.onreadystatechange = function(){ // Call a function when the state changes.
if (this.readyState === XMLHttpRequest.DONE && this.status === 200){
// Request finished. Do processing here.
t2 = performance.now();
console.log("Verification hash sum from server: ", xhr.response);
received_hashsum = xhr.response;
}
} // 1,3
if(itemType == "webpage" || itemType == "annotation"){
itemJSON = JSON.stringify({"webpage" : itemObject});
} // 7
if(itemType == "category"){
itemJSON = JSON.stringify({"category": itemObject});
}
/* Calculate hash sum before sync */
sent_hashsum = calculateHashsum(itemJSON);
/* Sync DB entry */
xhr.send(itemJSON);
/* Calculate time */
let sync_time = t1-t2;
/* Debug */
console.log("API call sent. Working from UUID: ", uuid.annotatorUUID, " Time in microseconds: ", sync_time, " Hash sum before sync: ", sent_hashsum);
/* Reset variables */
sync_time=null;
itemType = "";
/*
* If saveWebpageToPDF is set true, store all
* webpages as .pdf and sync with server
*
* if(saveWebpageToPDF == true){
*
*
* }
*
* */
}
function getDomain(url){
let domain = "";
/* There will be a problem with URLs with multiple top domains in it.
* -> Use https://developer.mozilla.org/en-US/docs/Web/API/URL/hostname instead
* const url = new URL('https://developer.mozilla.org/en-US/docs/Web/API/URL/hostname');
* console.log(url.hostname); // Logs: 'developer.mozilla.org' */
if(onionSitesOnly == true){
console.log("Ignored web page. Only storing .onion sites.");
if(url.includes(".onion")){
domain = url.split(".onion")[0] + ".onion";
}
}
if(onionSitesOnly == false){
domain = url.hostname;
/*
if(url.includes(".com")){
domain = url.split(".com")[0] + ".com";
}
else if(url.includes(".se")){
domain = url.split(".se")[0] + ".se";
}
else if(url.includes(".org")){
domain = url.split(".org")[0] + ".org";
}
else if(url.includes(".net")){
domain = url.split(".net")[0] + ".net";
}
else if(url.includes(".eu")){
domain = url.split(".eu")[0] + ".eu";
}
else if(url.includes(".co.uk")){
domain = url.split(".co.uk")[0] + ".co.uk";
}
else if(url.includes(".de")){
domain = url.split(".de")[0] + ".de";
}
else if(url.includes(".nu")){
domain = url.split(".nu")[0] + ".nu";
}
else{
domain = "unconventional";
}*/
}
return domain;
}
function getFromDatabase(){
//browser.storage.local.get().then(receivedFromDatabase, onError);
};
function setHighlightedText(text){
console.log("returning highlighted text.");
if(text == "get"){
console.log("| -- returning highlighted text.");
return highlightedText;
}
else{
var highlightedText = text;
console.log("|-- saving highlighted text", text);
}
}
function removeAllFromDatabase(){
browser.storage.local.clear().then(setItem, onError);
}
function receivedFromDatabase(item){
console.log("arr should be: ", item);
return item;
};
function gotItem(item){
console.log("DB response: Received item from local storage forwarding to function now.", item);
return item;
};
function setItem(){
console.log("Dummy debugger: Item inserted to local storage.");
};
function onSuccess(hashInput){
const hashArray = Array.from(new Uint8Array(hashInput));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('').toString();
return hashHex;
};
function onError(error){
console.log("Now there is an error with hashing: ", error);
};
function updateContent(){
var tabs = browser.tabs.query({currentWindow: true, active: true}).then((tabs) => {addToDatabase(tabs)});
currentTab = tabs;
/* Check connection to database */
/*browser.tabs.query({windowId: myWindowId, active: true}).then((tabs) => {return browser.storage.local.get(tabs[0].url);}).then((storedInfo) => {
console.log("tabs[0] ", storedInfo); //storedInfo[Object.keys(storedInfo)[0]];
});*/
};
/* Create a unqiue annotator ID. */
function createUUID(){
var nUUID = "";
var char_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for(var i=0; i < 8; i++ ){
nUUID += char_list.charAt(Math.floor(Math.random() * char_list.length));
}
console.log("Generated: ", nUUID);
return nUUID;
}
/* Check if username and UUID exists; otherwise, create it. */
async function getUUID(){
uuid = await browser.storage.local.get("annotatorUUID").then(gotItem, onError);
/* Create UUID if one does not already exist. */
if(uuid["annotatorUUID"] == undefined || uuid["annotatorUUID"] == ""){
uuid = {annotatorUUID: createUUID()};
await browser.storage.local.set(uuid).then(gotItem, onError);
}
else{
console.log("Annotator identified with UUID as: ", uuid);
}
}
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
function hex_hmac_md5(k, d)
{ return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function b64_hmac_md5(k, d)
{ return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function any_hmac_md5(k, d, e)
{ return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of a raw string
*/
function rstr_md5(s)
{
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function rstr_hmac_md5(key, data)
{
var bkey = rstr2binl(key);
if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
}
/*
* Convert a raw string to a hex string
*/
function rstr2hex(input)
{
try { hexcase } catch(e) { hexcase=0; }
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var output = "";
var x;
for(var i = 0; i < input.length; i++)
{
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F)
+ hex_tab.charAt( x & 0x0F);
}
return output;
}
/*
* Convert a raw string to a base-64 string
*/
function rstr2b64(input)
{
try { b64pad } catch(e) { b64pad=''; }
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var output = "";
var len = input.length;
for(var i = 0; i < len; i += 3)
{
var triplet = (input.charCodeAt(i) << 16)
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
| (i + 2 < len ? input.charCodeAt(i+2) : 0);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > input.length * 8) output += b64pad;
else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
}
}
return output;
}
/*
* Convert a raw string to an arbitrary string encoding
*/
function rstr2any(input, encoding)
{
var divisor = encoding.length;
var i, j, q, x, quotient;
/* Convert to an array of 16-bit big-endian values, forming the dividend */
var dividend = Array(Math.ceil(input.length / 2));
for(i = 0; i < dividend.length; i++)
{
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
}
/*
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
* forms the dividend for the next step. All remainders are stored for later
* use.
*/
var full_length = Math.ceil(input.length * 8 /
(Math.log(encoding.length) / Math.log(2)));
var remainders = Array(full_length);
for(j = 0; j < full_length; j++)
{
quotient = Array();
x = 0;
for(i = 0; i < dividend.length; i++)
{
x = (x << 16) + dividend[i];
q = Math.floor(x / divisor);
x -= q * divisor;
if(quotient.length > 0 || q > 0)
quotient[quotient.length] = q;
}
remainders[j] = x;
dividend = quotient;
}
/* Convert the remainders to the output string */
var output = "";
for(i = remainders.length - 1; i >= 0; i--)
output += encoding.charAt(remainders[i]);
return output;
}
/*
* Encode a string as utf-8.
* For efficiency, this assumes the input is valid utf-16.
*/
function str2rstr_utf8(input)
{
var output = "";
var i = -1;
var x, y;
while(++i < input.length)
{
/* Decode utf-16 surrogate pairs */
x = input.charCodeAt(i);
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
{
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
i++;
}
/* Encode output as utf-8 */
if(x <= 0x7F)
output += String.fromCharCode(x);
else if(x <= 0x7FF)
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
0x80 | ( x & 0x3F));
else if(x <= 0xFFFF)
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
else if(x <= 0x1FFFFF)
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
0x80 | ((x >>> 12) & 0x3F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
}
return output;
}
/*
* Encode a string as utf-16
*/
function str2rstr_utf16le(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
(input.charCodeAt(i) >>> 8) & 0xFF);
return output;
}
function str2rstr_utf16be(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
input.charCodeAt(i) & 0xFF);
return output;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binl(input)
{
var output = Array(input.length >> 2);
for(var i = 0; i < output.length; i++)
output[i] = 0;
for(var i = 0; i < input.length * 8; i += 8)
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
return output;
}
/*
* Convert an array of little-endian words to a string
*/
function binl2rstr(input)
{
var output = "";
for(var i = 0; i < input.length * 32; i += 8)
output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
return output;
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function binl_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/* Source :
https://www.quora.com/How-do-I-generate-sha256-key-in-javascript?share=1
*/
function SHA256(s){
var chrsz = 8;
var hexcase = 0;
function safe_add (x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
function S (X, n) { return ( X >>> n ) | (X << (32 - n)); }
function R (X, n) { return ( X >>> n ); }
function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }
function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }
function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }
function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }
function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }
function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }
function core_sha256 (m, l) {
var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 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);
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
var W = new Array(64);
var a, b, c, d, e, f, g, h, i, j;
var T1, T2;
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >> 9) << 4) + 15] = l;
for ( var i = 0; i<m.length; i+=16 ) {
a = HASH[0];
b = HASH[1];
c = HASH[2];
d = HASH[3];
e = HASH[4];
f = HASH[5];
g = HASH[6];
h = HASH[7];
for ( var j = 0; j<64; j++) {
if (j < 16) W[j] = m[j + i];
else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
T2 = safe_add(Sigma0256(a), Maj(a, b, c));
h = g;
g = f;
f = e;
e = safe_add(d, T1);
d = c;
c = b;
b = a;
a = safe_add(T1, T2);
}
HASH[0] = safe_add(a, HASH[0]);
HASH[1] = safe_add(b, HASH[1]);
HASH[2] = safe_add(c, HASH[2]);
HASH[3] = safe_add(d, HASH[3]);
HASH[4] = safe_add(e, HASH[4]);
HASH[5] = safe_add(f, HASH[5]);
HASH[6] = safe_add(g, HASH[6]);
HASH[7] = safe_add(h, HASH[7]);
}
return HASH;
}
function str2binb (str) {
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz) {
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
}
return bin;
}
function Utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}
function binb2hex (binarray) {
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++) {
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
s = Utf8Encode(s);
return binb2hex(core_sha256(str2binb(s), s.length * chrsz));
}
/* Update content when a new tab becomes active. */
browser.tabs.onActivated.addListener(updateContent);
/* "Authenticate" user */
getUUID();
/* Update content when a new page is loaded into a tab. */
browser.tabs.onUpdated.addListener(updateContent);
/* When the sidebar loads, get the ID of its window, and update its content.
*/
browser.windows.getCurrent({populate: true}).then((windowInfo) => {
myWindowId = windowInfo.id;
updateContent();
});