diff --git a/app/web/app.js b/app/web/app.js
index 0f808b2..20ba838 100644
--- a/app/web/app.js
+++ b/app/web/app.js
@@ -111,7 +111,7 @@ var encrypt = {
var senderPublicKeyString = {};
senderDerivedKey = this.deriveSharedKeySender(
receiverCompressedPublicKey, senderECKeyData.privateKey);
- console.log("senderDerivedKey", senderDerivedKey);
+ //console.log("senderDerivedKey", senderDerivedKey);
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
let secret = Crypto.AES.encrypt(data, senderKey);
return {
@@ -136,7 +136,7 @@ var encrypt = {
receiverDerivedKey = this.deriveReceiverSharedKey(senderPublicKeyString,
receiverECKeyData.privateKey);
- console.log("receiverDerivedKey", receiverDerivedKey);
+ //console.log("receiverDerivedKey", receiverDerivedKey);
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
let decryptMsg = Crypto.AES.decrypt(secret, receiverKey);
@@ -258,22 +258,6 @@ function logout(){
location.reload();
}
-function listProfiles(){
- console.log("listProfiles");
- var profileList = document.getElementById("profileList");
- profileList.innerHTML = "";
- for (p in profiles){
- var element = document.createElement("div");
- element.setAttribute("class", "media");
- element.innerHTML = `
-
- @${p}
-
`
- profileList.appendChild(element);
- }
- //document.getElementById("profileInfo").style.display = "none";
-}
-
var supernodeKBucket;
var superNodeList;
/*Kademlia DHT K-bucket implementation as a binary tree.*/
diff --git a/app/web/home.html b/app/web/home.html
index 6b7e00b..b0f30e2 100644
--- a/app/web/home.html
+++ b/app/web/home.html
@@ -26,7 +26,7 @@
Profiles
-

+
+
+
+
-
-
- TWEETS
- -
-
+
+
+ TWEETS
+
+
+
+
+
-
-
-
diff --git a/app/web/home.js b/app/web/home.js
index 27f02bf..fc08346 100644
--- a/app/web/home.js
+++ b/app/web/home.js
@@ -116,6 +116,11 @@ function getDatafromAPI(){
var objectStore4 = db.createObjectStore("lastTweet");
var objectStore5 = db.createObjectStore("followers");
var objectStore6 = db.createObjectStore("following");
+ var objectStore7 = event.target.result.createObjectStore("messages",{ keyPath: 'msgID' });
+ objectStore7.createIndex('time', 'time', { unique: false });
+ objectStore7.createIndex('text', 'text', { unique: false });
+ objectStore7.createIndex('floID', 'floID', { unique: false });
+ objectStore7.createIndex('type', 'type', { unique: false });
};
idb.onsuccess = function(event) {
var db = event.target.result;
@@ -322,6 +327,10 @@ function initselfWebSocket(){
db.close();
};
selfWebsocket.send(`U${data.floID}`);
+ }else if(data.message && data.to == selfID){
+ var msg = encrypt.decryptMessage(data.secret,data.pubVal)
+ if(encrypt.verify(msg,data.sign,profiles[data.from].pubKey))
+ storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
}else if(data.fromSuperNode && following.includes(data.floID)){
var tid = data.tid;
data = JSON.parse(data.data);
@@ -370,6 +379,24 @@ function initselfWebSocket(){
};
}
+function listProfiles(){
+ console.log("listProfiles");
+ document.getElementById("profileName").innerHTML=profiles[selfID].name;
+ document.getElementById("profileFloID").innerHTML='@'+selfID;
+ var profileList = document.getElementById("profileList");
+ profileList.innerHTML = "";
+ for (p in profiles){
+ var element = document.createElement("div");
+ element.setAttribute("class", "media");
+ element.innerHTML = `
+
+ @${p}
+
`
+ profileList.appendChild(element);
+ }
+ //document.getElementById("profileInfo").style.display = "none";
+}
+
function postTweet(){
var tweetBox = document.getElementById("tweetBox");
var tweet = tweetBox.value;
@@ -403,6 +430,20 @@ function storeTweet(data,tid){
};
}
+function storeMsg(data){
+ var idb = indexedDB.open("FLO_Tweet");
+ idb.onerror = function(event) {
+ console.log("Error in opening IndexedDB!");
+ };
+ idb.onsuccess = function(event) {
+ var db = event.target.result;
+ var obs = db.transaction("messages", "readwrite").objectStore("messages");
+ data.msgID = `${data.time}_${data.floID}`;
+ obs.add(data);
+ db.close();
+ };
+}
+
function sendTweetToSuperNode(data,tid){
kBucketObj.determineClosestSupernode(selfID).then(result=>{
var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws");
@@ -480,7 +521,7 @@ function createTweetElement(floID,time,tweet){
element.innerHTML = `
-
${tweet}
+
${tweet.replace(/\n/g, "
")}
diff --git a/app/web/msg.html b/app/web/msg.html
new file mode 100644
index 0000000..3d22f23
--- /dev/null
+++ b/app/web/msg.html
@@ -0,0 +1,123 @@
+
+
+
+ FLO Twitter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/web/msg.js b/app/web/msg.js
new file mode 100644
index 0000000..2edd34b
--- /dev/null
+++ b/app/web/msg.js
@@ -0,0 +1,210 @@
+var profiles;
+var receiverID,selfID,privKey;
+var selfwebsocket,receiverWebSocket,recStat;
+
+function initMsgs(){
+ if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined){
+ alert("Login credentials failed! Returning to home page!");
+ window.location.href = "home.html";
+ return;
+ }
+ profiles = JSON.parse(sessionStorage.profiles);
+ console.log(profiles);
+ privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey));
+ selfID = sessionStorage.selfID;
+ superNodeList = JSON.parse(sessionStorage.superNodeList);
+ kBucketObj.launchKBucket().then(function(result){
+ console.log(result)
+ initselfWebSocket();
+ readMsgfromIDB().then(function(result){
+ listProfiles();
+ document.getElementById("sendMsgInput").addEventListener("keyup",function(event){
+ if(event.keyCode === 13){
+ event.preventDefault();
+ sendMsg();
+ }
+ });
+ }).catch(function(error){
+ console.log(error);
+ });
+ }).catch(function(error){
+ console.log(error);
+ });
+}
+
+function listProfiles(){
+ console.log("listProfiles");
+ document.getElementById("profileName").innerHTML=profiles[selfID].name;
+ document.getElementById("profileFloID").innerHTML='@'+selfID;
+ var profileList = document.getElementById("profileList");
+ profileList.innerHTML = "";
+ for (p in profiles){
+ var element = document.createElement("div");
+ element.setAttribute("class", "media");
+ element.innerHTML = `
+
+ @${p}
+
`
+ profileList.appendChild(element);
+ }
+}
+
+function initselfWebSocket(){
+ selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
+ selfWebsocket.onopen = function(evt){
+ console.log("Connecting");
+ var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
+ selfWebsocket.send("$"+serverPass);
+ };
+ selfWebsocket.onclose = function(evt){
+ console.log("DISCONNECTED");
+ };
+ selfWebsocket.onmessage = function(evt){
+ console.log(evt.data);
+ if(evt.data[0] == '$')
+ return;
+ try{
+ data = JSON.parse(evt.data);
+ if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
+ var idb = indexedDB.open("FLO_Tweet");
+ idb.onsuccess = function(event) {
+ var db = event.target.result;
+ var obs = db.transaction("followers", "readwrite").objectStore("followers");
+ obs.add(data.sign,data.floID);
+ db.close();
+ };
+ selfWebsocket.send(`F${data.floID}-${data.sign}`);
+ }else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
+ var idb = indexedDB.open("FLO_Tweet");
+ idb.onsuccess = function(event) {
+ var db = event.target.result;
+ var obs = db.transaction("followers", "readwrite").objectStore("followers");
+ obs.delete(data.floID);
+ db.close();
+ };
+ selfWebsocket.send(`U${data.floID}`);
+ }else if(data.message && data.to == selfID){
+ var msg = encrypt.decryptMessage(data.secret,data.pubVal)
+ if(encrypt.verify(msg,data.sign,profiles[data.from].pubKey)){
+ createMsgElement(data.from,data.time,msg,'R')
+ storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
+ }
+ }
+ }catch(error){
+ console.log(error.message)
+ }
+ };
+ selfWebsocket.onerror = function(evt){
+ console.log(evt);
+ };
+}
+
+function readMsgfromIDB(){
+ return new Promise(
+ function(resolve,reject){
+ var disp = document.getElementById("msgsContainer");
+ for(floID in profiles){
+ var element = document.createElement('div');
+ element.setAttribute("id", floID);
+ element.style.display = 'none';
+ disp.appendChild(element);
+ }
+ var idb = indexedDB.open("FLO_Tweet");
+ idb.onerror = function(event) {
+ reject("Error in opening IndexedDB!");
+ };
+ idb.onsuccess = function(event) {
+ var db = event.target.result;
+ var obs = db.transaction("messages", "readwrite").objectStore("messages");
+ obs.openCursor().onsuccess = function(event) {
+ var cursor = event.target.result;
+ if(cursor) {
+ createMsgElement(cursor.value.floID,cursor.value.time,cursor.value.text,cursor.value.type);
+ cursor.continue();
+ } else {
+ console.log('Entries all displayed.');
+ resolve("Read Msg from IDB");
+ }
+ };
+ db.close();
+ };
+ }
+ );
+}
+
+function changeReceiver(floID){
+ try{
+ if(receiverID !== undefined)
+ document.getElementById(receiverID).style.display = 'none';
+ if(receiverWebSocket !== undefined && receiverWebSocket.readyState === WebSocket.OPEN)
+ receiverWebSocket.close();
+ }catch(e){
+ console.log(e);
+ }
+ console.log(floID);
+ receiverID = floID;
+ document.getElementById('recipient_floID').innerHTML = `${profiles[receiverID].name}
@${receiverID}`;
+ recStat = false;
+ document.getElementById(receiverID).style.display = 'block';
+ try{
+ receiverWebSocket = new WebSocket("ws://"+profiles[receiverID].onionAddr+"/ws");
+ receiverWebSocket.onopen = function(ev){ recStat = true; };
+ receiverWebSocket.onerror = function(ev) { recStat = false;};
+ receiverWebSocket.onclose = function(ev) { recStat = false; };
+ }catch(e){
+ console.log(e);
+ }
+}
+
+function sendMsg(){
+ if(receiverID === undefined){
+ alert("Select a contact and send message");
+ return;
+ }
+ var inp = document.getElementById('sendMsgInput')
+ var msg = inp.value
+ inp.value = ""
+ console.log(msg)
+ var time = Date.now()
+ var sign = encrypt.sign(msg,privKey)
+ var msgEncrypt = encrypt.encryptMessage(msg,profiles[receiverID].pubKey)
+ var data = JSON.stringify({message:true,from:selfID,to:receiverID,time:time,secret:msgEncrypt.secret,sign:sign,pubVal:msgEncrypt.senderPublicKeyString});
+
+ if(recStat)
+ receiverWebSocket.send(data);
+ else{
+ var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:receiverID,data:data})
+ sendDataToSuperNode(receiverID,SNdata)
+ }
+ console.log(`sentMsg : ${data}`);
+ createMsgElement(receiverID,time,msg,'S')
+ storeMsg({time:time,floID:receiverID,text:msg,type:'S'});
+}
+
+function createMsgElement(floID,time,msg,type){
+ var msgField = document.getElementById(floID);
+ var element = document.createElement("div");
+ element.setAttribute("class", "media");
+ element.innerHTML = `
+
+
+ ${msg}
+ ${getTime(time)}
+
+
`;
+ msgField.appendChild(element);
+}
+
+function storeMsg(data){
+ var idb = indexedDB.open("FLO_Tweet");
+ idb.onerror = function(event) {
+ console.log("Error in opening IndexedDB!");
+ };
+ idb.onsuccess = function(event) {
+ var db = event.target.result;
+ var obs = db.transaction("messages", "readwrite").objectStore("messages");
+ data.msgID = `${data.time}_${data.floID}`;
+ obs.add(data);
+ db.close();
+ };
+}
\ No newline at end of file
diff --git a/app/web/profile.html b/app/web/profile.html
index 6b723f5..4fd9dd7 100644
--- a/app/web/profile.html
+++ b/app/web/profile.html
@@ -27,7 +27,7 @@
Profiles
- Messages
+ Messages
@@ -49,8 +49,7 @@
-
-

+
diff --git a/app/web/profile.js b/app/web/profile.js
index 5f8b4a1..f32c19f 100644
--- a/app/web/profile.js
+++ b/app/web/profile.js
@@ -98,6 +98,22 @@ function displayTweetFromIDB(floID){
);
}
+function listProfiles(){
+ console.log("listProfiles");
+ var profileList = document.getElementById("profileList");
+ profileList.innerHTML = "";
+ for (p in profiles){
+ var element = document.createElement("div");
+ element.setAttribute("class", "media");
+ element.innerHTML = `
+
+ @${p}
+
`
+ profileList.appendChild(element);
+ }
+ //document.getElementById("profileInfo").style.display = "none";
+}
+
function createTweetElement(floID,time,tweet){
var tweetDisplay = document.getElementById("profileBody");
var element = document.createElement("div");
@@ -105,7 +121,7 @@ function createTweetElement(floID,time,tweet){
element.innerHTML = `
-
${tweet}
+
${tweet}
@@ -164,6 +180,20 @@ function storeTweet(data,id){
};
}
+function storeMsg(data){
+ var idb = indexedDB.open("FLO_Tweet");
+ idb.onerror = function(event) {
+ console.log("Error in opening IndexedDB!");
+ };
+ idb.onsuccess = function(event) {
+ var db = event.target.result;
+ var obs = db.transaction("messages", "readwrite").objectStore("messages");
+ data.msgID = `${data.time}_${data.floID}`;
+ obs.add(data);
+ db.close();
+ };
+}
+
function pingSuperNodeforNewTweets(floID){
getLastTweetCount(floID).then(function(result){
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
@@ -242,6 +272,10 @@ function initselfWebSocket(){
db.close();
};
selfWebsocket.send(`U${data.floID}`);
+ }else if(data.message && data.to == selfID){
+ var msg = encrypt.decryptMessage(data.secret,data.pubVal)
+ if(encrypt.verify(msg,data.sign,profiles[data.from].pubKey))
+ storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
}else if(data.fromSuperNode && data.floID == profileID){
var tid = data.tid;
data = JSON.parse(data.data);
diff --git a/app/web/styles.css b/app/web/styles.css
index a646d71..a678a1f 100644
--- a/app/web/styles.css
+++ b/app/web/styles.css
@@ -49,4 +49,33 @@ div.panel-heading{
.timestamp{
color : grey;
+}
+
+#msgsContainer{
+ overflow-y: auto;
+ height: calc(100% - 220px);
+}
+
+.msg-R{
+ float: left;
+ width: auto !important;
+ height: auto;
+ background: lightcyan;
+ border-radius: 10px 10px 10px 0;
+ padding: 4px 10px 7px !important;
+ font-size: 12px;
+ display: inline-block;
+ word-wrap: break-word;
+}
+
+.msg-S {
+ float: right;
+ width: auto !important;
+ height: auto;
+ background: lightcyan;
+ border-radius: 10px 10px 0 10px;
+ padding: 4px 10px 7px !important;
+ font-size: 12px;
+ display: inline-block;
+ word-wrap: break-word;
}
\ No newline at end of file