Update v0.8

This commit is contained in:
sairajzero 2019-04-18 22:07:34 +05:30
parent a8e46f38a2
commit 047bb9c000
16 changed files with 1722 additions and 846 deletions

View File

@ -9,10 +9,143 @@ if (!window.indexedDB) {
var contacts = [];
var receiverID,senderID;
var selfwebsocket;
var privKey = prompt("Enter Private Key : ")
var selfwebsocket,receiverWebSocket;
var privKey;
var encrypt = {
p: BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16),
exponent1: function () {
return encrypt.p.add(BigInteger.ONE).divide(BigInteger("4"))
},
calculateY: function (x) {
let p = this.p;
let exp = this.exponent1();
// x is x value of public key in BigInteger format without 02 or 03 or 04 prefix
return x.modPow(BigInteger("3"), p).add(BigInteger("7")).mod(p).modPow(exp, p)
},
// Insert a compressed public key
getUncompressedPublicKey: function (compressedPublicKey) {
const p = this.p;
// Fetch x from compressedPublicKey
let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey);
const prefix = pubKeyBytes.shift() // remove prefix
let prefix_modulus = prefix % 2;
pubKeyBytes.unshift(0) // add prefix 0
let x = new BigInteger(pubKeyBytes)
let xDecimalValue = x.toString()
// Fetch y
let y = this.calculateY(x);
let yDecimalValue = y.toString();
// verify y value
let resultBigInt = y.mod(BigInteger("2"));
let check = resultBigInt.toString() % 2;
if (prefix_modulus !== check) {
yDecimalValue = y.negate().mod(p).toString();
}
return {
x: xDecimalValue,
y: yDecimalValue
};
},
getSenderPublicKeyString: function () {
privateKey = ellipticCurveEncryption.senderRandom();
senderPublicKeyString = ellipticCurveEncryption.senderPublicString(privateKey);
return {
privateKey: privateKey,
senderPublicKeyString: senderPublicKeyString
}
},
deriveSharedKeySender: function (receiverCompressedPublicKey, senderPrivateKey) {
try {
let receiverPublicKeyString = this.getUncompressedPublicKey(
receiverCompressedPublicKey);
var senderDerivedKey = {
XValue: "",
YValue: ""
};
senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation(
receiverPublicKeyString.x,
receiverPublicKeyString.y, senderPrivateKey);
return senderDerivedKey;
} catch (error) {
return new Error(error);
}
},
deriveReceiverSharedKey: function (senderPublicKeyString, receiverPrivateKey) {
return ellipticCurveEncryption.receiverSharedKeyDerivation(
senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString,
receiverPrivateKey);
},
getReceiverPublicKeyString: function (privateKey) {
return ellipticCurveEncryption.receiverPublicString(privateKey);
},
deriveSharedKeyReceiver: function (senderPublicKeyString, receiverPrivateKey) {
try {
return ellipticCurveEncryption.receiverSharedKeyDerivation(senderPublicKeyString.XValuePublicString,
senderPublicKeyString.YValuePublicString, receiverPrivateKey);
} catch (error) {
return new Error(error);
}
},
encryptMessage: function (data, receiverCompressedPublicKey) {
var senderECKeyData = this.getSenderPublicKeyString();
var senderDerivedKey = {
XValue: "",
YValue: ""
};
var senderPublicKeyString = {};
senderDerivedKey = this.deriveSharedKeySender(
receiverCompressedPublicKey, senderECKeyData.privateKey);
console.log("senderDerivedKey", senderDerivedKey);
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
let secret = Crypto.AES.encrypt(data, senderKey);
return {
secret: secret,
senderPublicKeyString: senderECKeyData.senderPublicKeyString
};
},
decryptMessage: function (secret, senderPublicKeyString) {
var receiverDerivedKey = {
XValue: "",
YValue: ""
};
var receiverECKeyData = {};
var myPrivateKey = privKey;
if (typeof myPrivateKey !== "string") throw new Error("No private key found.");
let privateKey = this.wifToDecimal(myPrivateKey, true);
if (typeof privateKey.privateKeyDecimal !== "string") throw new Error(
"Failed to detremine your private key.");
receiverECKeyData.privateKey = privateKey.privateKeyDecimal;
receiverDerivedKey = this.deriveReceiverSharedKey(senderPublicKeyString,
receiverECKeyData.privateKey);
console.log("receiverDerivedKey", receiverDerivedKey);
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
let decryptMsg = Crypto.AES.decrypt(secret, receiverKey);
return decryptMsg;
},
var wallets = {
ecparams: EllipticCurve.getSECCurveByName("secp256k1"),
getPubKeyHex: function(privateKeyHex){
var key = new Bitcoin.ECKey(privateKeyHex);
@ -24,6 +157,11 @@ var privKey = prompt("Enter Private Key : ")
var pubkeyHex = key.getPubKeyHex();
return pubkeyHex;
},
getFLOIDfromPubkeyHex: function(pubkeyHex){
var key = new Bitcoin.ECKey().setPub(pubkeyHex);
var floID = key.getBitcoinAddress();
return floID;
},
sign: function (msg, privateKeyHex) {
var key = new Bitcoin.ECKey(privateKeyHex);
key.setCompressed(true);
@ -50,7 +188,21 @@ var privKey = prompt("Enter Private Key : ")
var verify = Bitcoin.ECDSA.verifyRaw(messageHashBigInteger, signature.r, signature.s,
publicKeyPoint);
return verify;
}
},
wifToDecimal: function(pk_wif, isPubKeyCompressed = false) {
let pk = Bitcoin.Base58.decode(pk_wif)
pk.shift()
pk.splice(-4, 4)
//If the private key corresponded to a compressed public key, also drop the last byte (it should be 0x01).
if (isPubKeyCompressed == true) pk.pop()
pk.unshift(0)
privateKeyDecimal = BigInteger(pk).toString()
privateKeyHex = Crypto.util.bytesToHex(pk)
return {
privateKeyDecimal: privateKeyDecimal,
privateKeyHex: privateKeyHex
}
}
}
function convertStringToInt(string){
@ -61,15 +213,18 @@ function userDataStartUp(){
console.log("StartUp");
getDatafromAPI().then(function (result) {
console.log(result);
getuserID().then(function(result){
console.log(result);
getDatafromIDB().then(function(result){
contacts = arrayToObject(result);
console.log(contacts);
displayContacts();
getDatafromIDB().then(function(result){
contacts = arrayToObject(result);
console.log(contacts);
getuserID().then(function(result){
console.log(result);
senderID = result;
alert(`${senderID}\nWelcome ${contacts[senderID].name}`)
readMsgfromIDB().then(function(result){
console.log(result);
initselfWebSocket();
displayContacts();
const createClock = setInterval(checkStatusInterval, 30000);
}).catch(function(error){
console.log(error.message);
});
@ -87,7 +242,7 @@ function userDataStartUp(){
function arrayToObject(array){
obj = {};
array.forEach(element => {
obj[element.floID] = {onionAddr : element.onionAddr, name : element.name};
obj[element.floID] = {onionAddr : element.onionAddr, name : element.name, pubKey : element.pubKey};
});
return obj;
}
@ -126,8 +281,9 @@ function userDataStartUp(){
};
idb.onupgradeneeded = function(event) {
var objectStore = event.target.result.createObjectStore("contacts",{ keyPath: 'floID' });
objectStore.createIndex('onionAddr', 'onionAddr', { unique: true });
objectStore.createIndex('onionAddr', 'onionAddr', { unique: false });
objectStore.createIndex('name', 'name', { unique: false });
objectStore.createIndex('pubKey', 'pubKey', { unique: false });
var objectStore2 = event.target.result.createObjectStore("lastTx");
};
idb.onsuccess = function(event) {
@ -162,7 +318,9 @@ function userDataStartUp(){
//return;
var data = JSON.parse(tx.floData).FLO_chat;
if(data !== undefined){
data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name};
if(encrypt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr)
throw("PublicKey doesnot match with floID")
data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name, pubKey:data.pubKey};
storedata(data).then(function (response) {
}).catch(function (error) {
console.log(error.message);
@ -190,57 +348,30 @@ function userDataStartUp(){
function getuserID(){
return new Promise(
function(resolve,reject){
var idb = indexedDB.open("FLO_Chat");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction('lastTx', "readwrite").objectStore('lastTx');
new Promise(function(res,rej){
var getReq = obs.get('userID');
getReq.onsuccess = function(event){
var userID = event.target.result;
if(userID === undefined){
userID = prompt("Enter A Valid Flo ID!");
while(!validateAddr(userID)){
userID = prompt("Retry!Enter A Valid Flo ID!");
}
var obs2 = db.transaction('contacts', "readwrite").objectStore('contacts');
var getReq2 = obs2.get(userID);
getReq2.onsuccess = function(event){
var data = event.target.result;
console.log(window.location.host);
//console.log(data.onionAddr);
if(data === undefined)
var reg = confirm('FLO ID is not registers to FLO chat!\nRegister FLO ID?');
else if(data.onionAddr == window.location.host)
res(userID);
else
var reg = confirm('FLO ID is registered to another onion!\nChange FLO ID to this onion?');
if(reg)
if(registerID(userID,window.location.host))
res(userID);
rej('Unable to register userID!\nTry again later!');
}
}
else
res(userID);
}
}).then(function(result){
console.log(result);
var obs = db.transaction('lastTx', "readwrite").objectStore('lastTx');
senderID = result;
obs.put(result,'userID');
db.close();
resolve('userID Initiated')
}).catch(function(error){
db.close();
console.log(error.message);
reject('userID Initiation Failed');
});
};
privKey = prompt("Enter FLO Private Key : ")
var key = new Bitcoin.ECKey(privKey);
while(key.priv == null){
privKey = prompt("Invalid FLO Private Key! Retry : ")
key = Bitcoin.ECKey(privKey);
}
key.setCompressed(true);
var userID = key.getBitcoinAddress();
if (contacts[userID] === undefined)
var reg = confirm(`${userID} is not registers to FLO chat!\nRegister FLO ID to this onion?`);
else if (contacts[userID].onionAddr == window.location.host)
resolve(userID)
else
var reg = confirm(`${userID} is registered to another onion!\nChange to this onion?`);
if(reg){
var name = prompt("Enter your name :");
var pubKey = key.getPubKeyHex();
if(registerID(userID,window.location.host,privKey,pubKey,name)){
contacts[userID] = {onionAddr : window.location.host, name : name, pubKey : pubKey};
resolve(userID);
}
}
reject(`Unable to bind ${userID} to this onionAddress!\nTry again later!`);
}
);
}
@ -333,7 +464,6 @@ function readMsgfromIDB(){
};
db.close();
};
}
);
}
@ -395,7 +525,8 @@ function initselfWebSocket(){
console.log(evt.data);
try{
var data = JSON.parse(evt.data);
if(!wallets.verify(data.msg,data.sign,data.pubKey))
var msg = encrypt.decryptMessage(data.secret,data.pubVal)
if(!encrypt.verify(msg,data.sign,contacts[data.from].pubKey))
return
var time = Date.now();
var disp = document.getElementById(data.from);
@ -404,7 +535,7 @@ function initselfWebSocket(){
msgdiv.innerHTML = `<div class="col-sm-12 message-main-receiver">
<div class="receiver">
<span class="message-text">
${data.msg}
${msg}
</span>
<span class="message-time pull-right">
${getTime(time)}
@ -412,7 +543,7 @@ function initselfWebSocket(){
</div>
</div>`;
disp.appendChild(msgdiv);
storeMsg({time:time,floID:data.from,text:data.msg,type:"R"});
storeMsg({time:time,floID:data.from,text:msg,type:"R"});
}catch(err){
if(evt.data[0]=='$')
alert(evt.data);
@ -425,13 +556,63 @@ function initselfWebSocket(){
};
}
function checkStatusInterval(){
try{
if(receiverWebSocket !== undefined && receiverWebSocket.readyState !== WebSocket.OPEN){
receiverWebSocket.close()
receiverWebSocket = new WebSocket("ws://"+contacts[receiverID].onionAddr+"/ws");
receiverWebSocket.onopen = function(evt){ receiverWebSocket.send('#') };
receiverWebSocket.onerror = function(ev) { receiverStatus(false); };
receiverWebSocket.onclose = function(ev) { receiverStatus(false); };
receiverWebSocket.onmessage = function(evt){
console.log(evt.data);
if(evt.data[0]=='#'){
if (evt.data[1]=='+')
receiverStatus(true);
else if(evt.data[1]=='-')
receiverStatus(false);
}
}
}
}catch(e){
console.log(e);
}
}
function changeReceiver(param){
if(receiverID !== undefined)
document.getElementById(receiverID).style.display = 'none';
console.log(param.getAttribute("name"));
receiverID = param.getAttribute("name");
document.getElementById('recipient-floID').innerHTML = receiverID;
receiverStatus(false)
document.getElementById(receiverID).style.display = 'block';
try{
if(receiverWebSocket !== undefined && receiverWebSocket.readyState === WebSocket.OPEN)
receiverWebSocket.close()
receiverWebSocket = new WebSocket("ws://"+contacts[receiverID].onionAddr+"/ws");
receiverWebSocket.onopen = function(ev){ receiverWebSocket.send('#'); };
receiverWebSocket.onerror = function(ev) { receiverStatus(false); };
receiverWebSocket.onclose = function(ev) { receiverStatus(false); };
receiverWebSocket.onmessage = function(evt){
console.log(evt.data);
if(evt.data[0]=='#'){
if (evt.data[1]=='+')
receiverStatus(true);
else if(evt.data[1]=='-')
receiverStatus(false);
}
}
}catch(e){
console.log(e);
}
}
function receiverStatus(status){
if(status)
document.getElementById('recipient-floID').style.backgroundColor = "#00b300";
else
document.getElementById('recipient-floID').style.backgroundColor = "#ff4d4d";
}
function getTime(time){
@ -452,15 +633,19 @@ function sendMsg(){
alert("Select a contact and send message");
return;
}
var msg = document.getElementById('sendMsgInput').value;
if(receiverWebSocket.readyState !== WebSocket.OPEN){
alert("Recipient is offline! Try again later")
return
}
var inp = document.getElementById('sendMsgInput')
var msg = inp.value;
inp.value = "";
console.log(msg);
var ws = new WebSocket("ws://"+contacts[receiverID].onionAddr+"/ws");
ws.onopen = function(evt){
var sign = wallets.sign(msg,privKey)
var pubkeyHex = wallets.getPubKeyHex(privKey)
var data = JSON.stringify({from:senderID,msg:msg,sign:sign,pubKey:pubkeyHex});
ws.send(data);
console.log(`sentMsg : ${data}`);
var sign = encrypt.sign(msg,privKey)
var msgEncrypt = encrypt.encryptMessage(msg,contacts[receiverID].pubKey)
var data = JSON.stringify({from:senderID,secret:msgEncrypt.secret,sign:sign,pubVal:msgEncrypt.senderPublicKeyString});
receiverWebSocket.send(data);
console.log(`sentMsg : ${data}`);
time = Date.now();
var disp = document.getElementById(receiverID);
var msgdiv = document.createElement('div');
@ -476,11 +661,4 @@ function sendMsg(){
</div>`;
disp.appendChild(msgdiv);
storeMsg({time:time,floID:receiverID,text:msg,type:"S"});
//send_check = 1;
//recursion_called = 0;
//addSentChat(msg.substring(2+msgArray[0].length+msgArray[1].length),timer,msgArray[0]);
//addTick(message);
}
ws.onerror = function(ev) { console.log(ev); };
ws.onclose = function(ev) { console.log(ev); };
}

View File

@ -59,7 +59,6 @@
<div class="col-sm-8 col-xs-8 heading-name">
<span class="heading-name-meta" id="recipient-floID">Select Contact
</span>
<span class="heading-online" id="recipient-status">Unknown</span>
</div>
<div class="col-sm-1 col-xs-1 heading-dot pull-right">
<i class="fa fa-ellipsis-v fa-2x pull-right" aria-hidden="true"></i>

File diff suppressed because it is too large Load Diff

BIN
app/websocket_chat Executable file

Binary file not shown.

734
app2.js
View File

@ -1,734 +0,0 @@
var displayAddress = "F6LUnwRRjFuEW97Y4av31eLqqVMK9FrgE2";
var floidToOnion = {};
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
if (!window.indexedDB) {
window.alert("Your browser doesn't support a stable version of IndexedDB.")
}
function convertStringToInt(string){
return parseInt(string,10);
}
let ajax = function (uri, params, req_type, callback) {
let url = `https://livenet.flocha.in/${uri}`;
let response = {};
var http = new XMLHttpRequest();
http.open(req_type, url, true);
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
response.success = true;
response.data = http.responseText;
callback(response.data);
} else {
response.success = false;
}
}
http.send(params);
}
function getTotalPages(address){
var uri = "api/txs/?address="+address;
try {
let res = ajax(uri, null, 'GET', function (response) {
try {
let data = JSON.parse(response);
getTransactionsByPage(address,convertStringToInt(data["pagesTotal"]+''));
} catch (error) {
console.log(error);
}
});
} catch (error) {
console.error(error);
}
}
function getTransactionsByPage(address,totalPages){
var cnt = 0;
for(var i=0;i<totalPages;i++){
var uri = "api/txs/?address="+address+"&pageNum="+i.toString();
try {
let res = ajax(uri, null, 'GET', function (response) {
try {
let data = JSON.parse(response);
getDataFromTransactions(data["txs"]);
cnt++;
if(cnt === totalPages)
checkIdStorageIndexdb();
} catch (error) {
console.log(error);
}
});
} catch (error) {
console.error(error);
}
}
}
function getDataFromTransactions(txid){
var len = txid.length;
var senderAddr='';
for(var i=0;i<len;i++){
var transaction = txid[i];
senderAddr = transaction["vin"]["0"]["addr"] + '';
if(senderAddr !== displayAddress)
continue;
var transactionData = transaction["floData"];
if(transactionData.startsWith('FloId:')){
try{
transactionData = JSON.parse(transactionData.split('FloId:')[1]);
mapIdToOnion(transactionData);
}catch(error){
console.log(error);
continue;
}
}
}
}
function mapIdToOnion(transactionData){
for(var key in transactionData)
floidToOnion[key] = transactionData[key];
// console.log(transactionData);
}
function checkIdStorageIndexdb(){
//console.log("Hello");
var request = window.indexedDB.open("floDbs", 3);
var db,floId;
request.onerror = function(event) {
console.log("error: ",event.target);
};
request.onsuccess = function(event) {
db = request.result;
console.log("success: "+ db);
var objectStore = db.transaction(["floid"],"readwrite").objectStore("floid");
objectStore.onerror = function(event) {
console.log("No Store Found!");
}
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
floId = cursor.value.id;
cursor.continue();
} else {
console.log("No more entries!");
if(floId === undefined){
floId = prompt("Enter A Valid Flo ID!");
while(floidToOnion[floId] === undefined)
floId = prompt("Retry!Enter A Valid Flo ID!");
storeFloIdIndexdb(floId+'');
}
else
executeNow(floId);
}
};
objectStore.openCursor().onerror = function(event) {
console.log("No entries found!");
};
};
request.onupgradeneeded = function(event) {
console.log('upgrade');
db = event.target.result;
var objectStore = db.createObjectStore("floid", {keyPath:"id", autoIncrement:true});
}
}
function storeFloIdIndexdb(floId){
var db;
var request = window.indexedDB.open("floDbs", 3);
request.onerror = function(event) {
console.log("error: ",event.target);
};
request.onsuccess = function(event) {
db = request.result;
console.log("success: "+ db);
request = db.transaction(["floid"], "readwrite")
.objectStore("floid")
.add({id:floId});
request.onsuccess = function(event) {
console.log("Floid has been added to your database.");
executeNow(floId+'');
};
request.onerror = function(event) {
console.log("Unable to add Floid in your database! ");
}
};
request.onupgradeneeded = function(event) {
db = event.target.result;
var objectStore = db.createObjectStore("floid", {keyPath:"id", autoIncrement:true});
}
}
getTotalPages(displayAddress);
function executeNow(floId){
for(var key in floidToOnion){
//console.log(floidToOnion[key]);
if(key !== floId ){
var listElement = document.getElementById('contact-list');
var createLi = document.createElement('li');
createLi.innerHTML = key;
listElement.appendChild(createLi);
}
}
var ulElement = document.getElementById('contact-list');
var prevSelectedElement = '';
var recipientId = '';
var db,timing;
var conversation = document.querySelector('.conversation-container');
var isNetwork;
var recursion_called,blueTickFlag = 0;
//requestForDb();//Needed to be fixed
if (navigator.onLine) {
isNetwork = 1;
} else {
isNetwork = 0;
}
ulElement.onclick = function(event){
event = event || window.event;
var target = event.target || event.srcElement;
console.log(target);
if(target.getAttribute("class") === "button__badge")
return;
if(prevSelectedElement !== ''){
prevSelectedElement.style.color = "#00ff00";
}
target.style.color = "red";
var spanTag = target.getElementsByTagName('span')[0];
if(spanTag !== undefined){
spanTag.parentNode.removeChild(spanTag);
//send to selected id from floid to add blue tick to chats of floid in selectedid user
}
recipientId = target.innerHTML;
document.getElementsByClassName('user')[0].innerHTML = recipientId+'';
//Determine Network Status Of Recipient
makeOffline();
addNetworkStatusOfRecipient(recipientId);
//conversation.innerHTML = "";
if(db === undefined)
requestForDb();
else
{
document.getElementsByClassName('input-msg')[0].setAttribute("placeholder","Type A Message!")
document.getElementsByClassName('input-msg')[0].disabled = false;
recursion_called = 0;
readFromDb(recipientId);
}
prevSelectedElement = target;
console.log(target.innerHTML);
}
function addNetworkStatusOfRecipient(recipientId){
var checkSocket;
if(recipientId == 'id2')
checkSocket = new WebSocket("ws://"+floidToOnion[recipientId]+":8000/ws");
else
checkSocket = new WebSocket("ws://"+floidToOnion[recipientId]+"/ws");
checkSocket.onopen = function(event){
makeOnline();
};
checkSocket.onclose = function(event){
makeOffline();
};
checkSocket.onerror = function(event){
makeOffline();
if(isNetwork === 0)
document.getElementsByClassName('status')[0].innerHTML = "Unknown";
console.log('error network');
//if(isNetwork === 1)
//addNetworkStatusOfRecipient(recipientId);
};
}
function requestForDb(){
var request = window.indexedDB.open("Database1", 3);
request.onerror = function(event) {
console.log("error: ",event.target);
};
request.onsuccess = function(event) {
db = request.result;
console.log("success: "+ db);
document.getElementsByClassName('input-msg')[0].setAttribute("placeholder","Type A Message!")
document.getElementsByClassName('input-msg')[0].disabled = false;
readFromDb(recipientId);
};
request.onupgradeneeded = function(event) {
db = event.target.result;
var objectStore = db.createObjectStore("chats", {keyPath:"id", autoIncrement:true});
}
}
function requestForUnknownDb(msg,timing,senderId){
var request = window.indexedDB.open("Database1", 3);
request.onerror = function(event) {
console.log("error: ",event.target);
};
request.onsuccess = function(event) {
db = request.result;
console.log("success: "+ db);
addReceivedChat(msg,timing,senderId);
};
request.onupgradeneeded = function(event) {
db = event.target.result;
var objectStore = db.createObjectStore("chats", {keyPath:"id", autoIncrement:true});
}
}
function addUnsentChat(msg,time,selectedId){
var request = db.transaction(["chats"], "readwrite")
.objectStore("chats")
.add({chat:"U"+selectedId+' '+msg,moment:time});
request.onsuccess = function(event) {
console.log("UnsentMessage has been added to your database.");
};
request.onerror = function(event) {
console.log("Unable to add message in your database! ");
}
}
function addSentChat(msg,time,selectedId){
var request = db.transaction(["chats"], "readwrite")
.objectStore("chats")
.add({chat:"S"+selectedId+msg,moment:time});
request.onsuccess = function(event) {
console.log("Message has been added to your database.");
};
request.onerror = function(event) {
console.log("Unable to add message in your database! ");
}
}
function addReceivedChat(msg,time,selectedId){
var request = db.transaction(["chats"], "readwrite")
.objectStore("chats")
.add({chat:"R"+selectedId+msg,moment:time});
request.onsuccess = function(event) {
console.log("Message has been added to your database.");
};
request.onerror = function(event) {
console.log("Unable to add message in your database! ");
}
}
function readFromDb(selectedId) {
conversation.innerHTML = "";
console.log("Bllllllllllllllllllllllllaaaaaaaaaaank");
var objectStore = db.transaction(["chats"],"readwrite").objectStore("chats");
objectStore.onerror = function(event) {
console.log("No Store Found!");
}
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
if(cursor.value.chat[0] === 'U'){
console.log(cursor.value.chat);
var len = cursor.value.chat.length;
var timeSent = cursor.value.moment;
var toSendId = '';
for(var i=1;i<len;i++){
if(cursor.value.chat[i] !== ' ')
toSendId = toSendId + cursor.value.chat[i];
else
break;
}
console.log(recipientId+" checking "+toSendId);
if(toSendId === recipientId){
var idLen = toSendId.length;
var msgToSend = cursor.value.chat.substring(idLen+2);
var message = buildUnSentMessage(msgToSend,timeSent);
//console.log("APPENDED",message);
conversation.appendChild(message);
conversation.scrollTop = conversation.scrollHeight;
var req = cursor.delete();
req.onsuccess = function() {
console.log('Deleted');
//time to resend
//After deleting ,i also need to add to frontend,time icon to tick
//Need to build a msg with no tick and add to conversation
//console.log(msgToSend,timeSent);
recursion_called = 0;
sendMessage(toSendId+" "+floId+" "+msgToSend,timeSent,message);
};
}
}
else{
var len = selectedId.length;
var check = 0;
for(var i=0;i<len;i++)
if(cursor.value.chat[i+1] !== selectedId[i])
{
check = 1;
break;
}
if(check === 0)
addChatToFrontEnd(len,cursor.value.chat,cursor.value.moment);
}
cursor.continue();
} else {
console.log("No more entries!");
}
};
objectStore.openCursor().onerror = function(event) {
console.log("No entries found!");
};
}
function addChatToFrontEnd(selectedIdLen,msg,time){
var orig_msg = msg.substring(1+selectedIdLen);
if(msg[0] == 'R')
var message = buildMessageReceived(orig_msg,time);
else if(msg[0] == 'S')
var message = buildMessageSent(orig_msg,time);
console.log("APPENDED",message);
conversation.appendChild(message);
//animateMessage(message);
conversation.scrollTop = conversation.scrollHeight;
}
var deviceTime = document.querySelector('.status-bar .time');
var messageTime = document.querySelectorAll('.message .time');
deviceTime.innerHTML = moment().format('h:mm A');
setInterval(function(){
deviceTime.innerHTML = moment().format('h:mm A');
}, 1000);
setInterval(function(){
console.log("Checking network status after 1 min");
if(recipientId !== '' && isNetwork === 1)
addNetworkStatusOfRecipient(recipientId);
console.log(recursion_called);
if(recursion_called === 6){
recursion_called = 0;
readFromDb(recipientId);
}
},80000);
for (var i = 0; i < messageTime.length; i++){
messageTime[i].innerHTML = moment().format('h:mm A');
}
var host = location.hostname //location.hostname
var wsUri = "ws://"+host+":8000/ws";
console.log(wsUri);
console.log(floidToOnion["id1"]);
console.log(floidToOnion["id2"]);
var websocket;
var recipient_websocket;
//var noOfUsersOnline = 0;
init();
function init(){
//readFromDb();
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt){
console.log("CONNECTED",floId);
websocket.send(floId+'$');
//makeOnline();
//noOfUsersOnline++;
//console.log("Total Users = "+noOfUsersOnline.toString());
//document.getElementsByClassName('user')[0].innerHTML = host+'';
}
function onClose(evt){
console.log("DISCONNECTED");
//makeOffline();
//noOfUsersOnline--;
//console.log("Total Users = "+noOfUsersOnline.toString());
}
function onMessage(evt){
console.log(evt.data);
var msgArray = evt.data.split(' ');
console.log("Message Received ",msgArray);
if(msgArray[1] !== floId)
return;
var len = msgArray.length;
var msg = "";
for(var i=3;i<len-1;i++)
msg = msg + msgArray[i] + ' ';
msg = msg + msgArray[len-1];
msg = msg.replace(/</g, "&lt;").replace(/>/g, "&gt;");
//console.log(msg);
var message = buildMessageReceived(msg,moment().format('h:mm A'));
if(msgArray[2] === recipientId){
conversation.appendChild(message);
//add blue tick to the sender of received message
}
else{
//implement badge unread message
var contactListElement = document.getElementById('contact-list');
//console.log(typeof contactListElement.innerHTML);
var items = contactListElement.getElementsByTagName('li');
var itemsLen = items.length;
for(var i=0;i<itemsLen;i++){
if(items[i].innerHTML.startsWith(msgArray[2])){
var spanTag = items[i].getElementsByTagName('span')[0];
if(spanTag === undefined){
var createSpan = document.createElement('span');
createSpan.setAttribute("class","button__badge");
createSpan.innerHTML = "1";
items[i].appendChild(createSpan);
break;
}
else{
var counter = parseInt(spanTag.innerHTML);
counter++;
spanTag.innerHTML = counter+'';
break;
}
}
}
}
if(db === undefined)
requestForUnknownDb(msg,timing,msgArray[2]);
else
addReceivedChat(msg,timing,msgArray[2]);
//animateMessage(message);
conversation.scrollTop = conversation.scrollHeight;
}
function onError(evt){
console.log(evt.data);
}
var form = document.querySelector('.conversation-compose');
form.addEventListener('submit', newMessage);
function newMessage(e) {
var input = e.target.input;
var temp_input = '';
if(input.value){
input.value = input.value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
//console.log(input.value);
var message = buildUnSentMessage(input.value,moment().format('h:mm A')); //Need to change span tag of build
console.log(message);
console.log("APPENDED",message);
conversation.appendChild(message);
//animateMessage(message);
console.log("Network Status",isNetwork);
temp_input = input.value;
if(isNetwork === 0){
console.log("Network Status Offline");
addUnsentChat(temp_input,timing,recipientId);
input.value = '';
conversation.scrollTop = conversation.scrollHeight;
e.preventDefault();
return;
}
//websocket.send(input.value);
/*recipient_websocket.onopen = function(event){
recipient_websocket.send(recipientId+" "+floId+" "+temp_input);
//recipient_websocket.close();
}
recipient_websocket.onerror = function(event){
console.log("Message Not Sent To Recipient!Try Again!");
}*/
recursion_called = 0;
sendMessage(recipientId+" "+floId+" "+temp_input,timing,message);
}
input.value = '';
conversation.scrollTop = conversation.scrollHeight;
e.preventDefault();
}
function sendMessage(msg,timer,message){
// Wait until the state of the socket is not ready and send the message when it is...
var msgArray = msg.split(' ');
var ws,send_check = 0;
console.log('check');
if(msgArray[0] === "id2")
ws = new WebSocket("ws://"+floidToOnion[msgArray[0]]+":8000/ws");
else
ws = new WebSocket("ws://"+floidToOnion[msgArray[0]]+"/ws");
ws.onopen = function(evt){
console.log('open');
ws.send(msg);
send_check = 1;
recursion_called = 0;
addSentChat(msg.substring(2+msgArray[0].length+msgArray[1].length),timer,msgArray[0]);
addTick(message);
}
ws.onclose = function(evt){
console.log("connection closed");
if(network === 1 && send_check === 0 && recursion_called <= 5){
recursion_called++;
sendMessage(msg,timer,message);
return;
}
addUnsentChat(msg.substring(2+msgArray[0].length+msgArray[1].length),timer,msgArray[0]);
}
ws.onerror = function(evt){
console.log('error');
if(isNetwork === 1 && send_check === 0 && recursion_called <= 5){
recursion_called++;
sendMessage(msg,timer,message);
return;
}
addUnsentChat(msg.substring(2+msgArray[0].length+msgArray[1].length),timer,msgArray[0]);
//conversation.innerHTML = "";
//readFromDb(msgArray[0]);
}
}
function buildUnSentMessage(text,time) {
var element = document.createElement('div');
timing = time;
element.classList.add('message', 'sent');
element.innerHTML = text +
'<span class="metadata">' +
'<span class="time">' + time + '</span>' + '<span data-icon="msg-time" class="unsend_msg"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 15" width="16" height="15"><path fill="#859479" d="M9.75 7.713H8.244V5.359a.5.5 0 0 0-.5-.5H7.65a.5.5 0 0 0-.5.5v2.947a.5.5 0 0 0 .5.5h.094l.003-.001.003.002h2a.5.5 0 0 0 .5-.5v-.094a.5.5 0 0 0-.5-.5zm0-5.263h-3.5c-1.82 0-3.3 1.48-3.3 3.3v3.5c0 1.82 1.48 3.3 3.3 3.3h3.5c1.82 0 3.3-1.48 3.3-3.3v-3.5c0-1.82-1.48-3.3-3.3-3.3zm2 6.8a2 2 0 0 1-2 2h-3.5a2 2 0 0 1-2-2v-3.5a2 2 0 0 1 2-2h3.5a2 2 0 0 1 2 2v3.5z"></path></svg></span>';
return element;
}
function buildMessageSent(text,time) {
var element = document.createElement('div');
timing = time;
element.classList.add('message', 'sent');
element.innerHTML = text +
'<span class="metadata">' +
'<span class="time">' + time + '</span>' +
'<span class="tick tick-animation">' +
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" id="msg-dblcheck" x="2047" y="2061"><path d="M15.01 3.316l-.478-.372a.365.365 0 0 0-.51.063L8.666 9.88a.32.32 0 0 1-.484.032l-.358-.325a.32.32 0 0 0-.484.032l-.378.48a.418.418 0 0 0 .036.54l1.32 1.267a.32.32 0 0 0 .484-.034l6.272-8.048a.366.366 0 0 0-.064-.512zm-4.1 0l-.478-.372a.365.365 0 0 0-.51.063L4.566 9.88a.32.32 0 0 1-.484.032L1.892 7.77a.366.366 0 0 0-.516.005l-.423.433a.364.364 0 0 0 .006.514l3.255 3.185a.32.32 0 0 0 .484-.033l6.272-8.048a.365.365 0 0 0-.063-.51z" fill="#92a58c"/></svg>' +
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" id="msg-dblcheck-ack" x="2063" y="2076"><path d="M15.01 3.316l-.478-.372a.365.365 0 0 0-.51.063L8.666 9.88a.32.32 0 0 1-.484.032l-.358-.325a.32.32 0 0 0-.484.032l-.378.48a.418.418 0 0 0 .036.54l1.32 1.267a.32.32 0 0 0 .484-.034l6.272-8.048a.366.366 0 0 0-.064-.512zm-4.1 0l-.478-.372a.365.365 0 0 0-.51.063L4.566 9.88a.32.32 0 0 1-.484.032L1.892 7.77a.366.366 0 0 0-.516.005l-.423.433a.364.364 0 0 0 .006.514l3.255 3.185a.32.32 0 0 0 .484-.033l6.272-8.048a.365.365 0 0 0-.063-.51z" fill="#4fc3f7"/></svg>' +
'</span>' +
'</span>';
return element;
}
function buildMessageReceived(text,time) {
var element = document.createElement('div');
timing = time;
element.classList.add('message', 'received');
element.innerHTML = text +
'<span class="metadata">' +
'<span class="time">' + time + '</span>' +
'<span class="tick tick-animation">' +
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" id="msg-dblcheck" x="2047" y="2061"><path d="M15.01 3.316l-.478-.372a.365.365 0 0 0-.51.063L8.666 9.88a.32.32 0 0 1-.484.032l-.358-.325a.32.32 0 0 0-.484.032l-.378.48a.418.418 0 0 0 .036.54l1.32 1.267a.32.32 0 0 0 .484-.034l6.272-8.048a.366.366 0 0 0-.064-.512zm-4.1 0l-.478-.372a.365.365 0 0 0-.51.063L4.566 9.88a.32.32 0 0 1-.484.032L1.892 7.77a.366.366 0 0 0-.516.005l-.423.433a.364.364 0 0 0 .006.514l3.255 3.185a.32.32 0 0 0 .484-.033l6.272-8.048a.365.365 0 0 0-.063-.51z" fill="#92a58c"/></svg>' +
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" id="msg-dblcheck-ack" x="2063" y="2076"><path d="M15.01 3.316l-.478-.372a.365.365 0 0 0-.51.063L8.666 9.88a.32.32 0 0 1-.484.032l-.358-.325a.32.32 0 0 0-.484.032l-.378.48a.418.418 0 0 0 .036.54l1.32 1.267a.32.32 0 0 0 .484-.034l6.272-8.048a.366.366 0 0 0-.064-.512zm-4.1 0l-.478-.372a.365.365 0 0 0-.51.063L4.566 9.88a.32.32 0 0 1-.484.032L1.892 7.77a.366.366 0 0 0-.516.005l-.423.433a.364.364 0 0 0 .006.514l3.255 3.185a.32.32 0 0 0 .484-.033l6.272-8.048a.365.365 0 0 0-.063-.51z" fill="#4fc3f7"/></svg>' +
'</span>' +
'</span>';
return element;
}
function blueTickMessage(message) {
setTimeout(function() {
var tick = message.querySelector('.tick');
tick.classList.remove('tick-animation');
}, 500);
}
function addTick(message) {
setTimeout(function() {
var timerElement = message.querySelector('.unsend_msg');
timerElement.outerHTML = '<span class="tick tick-animation">' +
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" id="msg-dblcheck" x="2047" y="2061"><path d="M15.01 3.316l-.478-.372a.365.365 0 0 0-.51.063L8.666 9.88a.32.32 0 0 1-.484.032l-.358-.325a.32.32 0 0 0-.484.032l-.378.48a.418.418 0 0 0 .036.54l1.32 1.267a.32.32 0 0 0 .484-.034l6.272-8.048a.366.366 0 0 0-.064-.512zm-4.1 0l-.478-.372a.365.365 0 0 0-.51.063L4.566 9.88a.32.32 0 0 1-.484.032L1.892 7.77a.366.366 0 0 0-.516.005l-.423.433a.364.364 0 0 0 .006.514l3.255 3.185a.32.32 0 0 0 .484-.033l6.272-8.048a.365.365 0 0 0-.063-.51z" fill="#92a58c"/></svg>' +
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" id="msg-dblcheck-ack" x="2063" y="2076"><path d="M15.01 3.316l-.478-.372a.365.365 0 0 0-.51.063L8.666 9.88a.32.32 0 0 1-.484.032l-.358-.325a.32.32 0 0 0-.484.032l-.378.48a.418.418 0 0 0 .036.54l1.32 1.267a.32.32 0 0 0 .484-.034l6.272-8.048a.366.366 0 0 0-.064-.512zm-4.1 0l-.478-.372a.365.365 0 0 0-.51.063L4.566 9.88a.32.32 0 0 1-.484.032L1.892 7.77a.366.366 0 0 0-.516.005l-.423.433a.364.364 0 0 0 .006.514l3.255 3.185a.32.32 0 0 0 .484-.033l6.272-8.048a.365.365 0 0 0-.063-.51z" fill="#4fc3f7"/></svg>' +
'</span>' +
'</span>';
//tick.classList.remove('tick-animation');
}, 500);
}
window.addEventListener('online', function(e) {
console.log('And we\'re back :).');
//conversation.innerHTML = "";
if(recipientId !== '' && recipientId !== undefined){
addNetworkStatusOfRecipient(recipientId);
readFromDb(recipientId);
}
//makeOnline();
isNetwork = 1;
//alert('You Have Been Disconnected!');
//window.location.href = floidToOnion[floId];
}, false);
window.addEventListener('offline', function(e) {
console.log('Connection is down.');
//makeOffline();
if(recipientId !== '' && recipientId !== undefined)
document.getElementsByClassName('status')[0].innerHTML = "Unknown";
isNetwork = 0;
}, false);
function makeOnline(){
console.log(document.getElementsByClassName('status')[0]);
document.getElementsByClassName('status')[0].innerHTML = "Online";
}
function makeOffline(){
document.getElementsByClassName('status')[0].innerHTML = "Offline";
}
//window.addEventListener("load", init, false);
}

37
autogen.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/sh
echo "----------Welcome to FLO-Whatsapp AutoGen----------"
if [ -f start ]; then
echo "FLO-Whatsapp is already AutoGen"
echo "To start run :\n./start <server-password>"
exit 0
fi
echo "----------Installing TOR----------"
sudo apt-get install tor
echo "----------Configuring Tor for FLO-Whatsapp----------"
echo $PWD
sudo cat <<EOT >> /etc/tor/torrc
HiddenServiceDir $PWD/.hidden_service/
HiddenServicePort 8000 127.0.0.1:8000
EOT
sudo chmod 700 $PWD
echo "----------Finished Configuring----------"
echo "----------Creating Start script----------"
cat > start << EOF
#!/bin/sh
if [ -z "\$1" ];then
echo "Enter server password as argument"
exit 0
fi
app/websocket_chat \$1 &
tor &
sleep 5s
OA=\$(cat .hidden_service/hostname)
zenity --info --text="Open link '\$OA:8000' in onion browser"
wait
EOF
chmod u+x start
echo "----------Finished AutoGen----------"
echo "To start run :\n./start <server-password>"

View File

@ -1,13 +0,0 @@
#!/bin/sh
echo "----------Welcome to FLO-Whatsapp installation----------"
echo "----------Installing TOR----------"
apt-get install tor
echo "----------Configuring Tor for FLO-Whatsapp----------"
echo $PWD
cat <<EOT >> /etc/tor/torrc
HiddenServiceDir $PWD/.hidden_service/
HiddenServicePort 8000 127.0.0.1:8000
EOT
chmod 700 $PWD
echo "----------Finished Configuring----------"

View File

@ -23,9 +23,6 @@ static int is_websocket(const struct mg_connection *nc) {
static void broadcast(struct mg_connection *nc, const struct mg_str msg) {
struct mg_connection *c;
char buf[500];
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
snprintf(buf, sizeof(buf), "%.*s", (int) msg.len, msg.p);
printf("%s\n", buf); /* Local echo. */
@ -66,9 +63,16 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
unicast(selfClient,mg_mk_str("$Another login is encountered! Please close/refresh this window"));
selfClient = nc;
unicast(selfClient,mg_mk_str("$Access Granted!"));
broadcast(nc, mg_mk_str("#+"));
}else
unicast(nc,mg_mk_str("$Access Denied!"));
}
else if(d.p[0] == '#'){
if(selfClient == NULL)
unicast(nc,mg_mk_str("#-"));
else
unicast(nc,mg_mk_str("#+"));
}
else
unicast(selfClient,d);
break;
@ -80,9 +84,10 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
case MG_EV_CLOSE: {
/* Disconnect. Tell everybody. */
if (is_websocket(nc)) {
if(nc == selfClient)
if(nc == selfClient){
selfClient = NULL;
//broadcast(nc, mg_mk_str("-- left"));
broadcast(nc, mg_mk_str("#-"));
}
}
break;
}

Binary file not shown.