diff --git a/src/frontend/index.css b/src/frontend/index.css
index 0170aad..705a206 100644
--- a/src/frontend/index.css
+++ b/src/frontend/index.css
@@ -58,7 +58,7 @@ input[type="file"] {
padding: 20px 70px;
background-color: #2B2F31;
border-radius: 10px;
- font-size: 1.3em;
+ font-size: 1.2em;
}
.popup_background {
height: 100%;
@@ -117,6 +117,15 @@ input[type="file"] {
display: inline-block;
vertical-align: middle;
}
+.popup .session_info h2 {
+ text-align: center;
+}
+.popup .session_info p:first-of-type, .popup .session_info pre {
+ display: inline-block;
+}
+.popup .session_info p:nth-of-type(2) {
+ margin-top: 0;
+}
.button_row {
display: flex;
gap: 15px;
@@ -156,6 +165,13 @@ input[type="file"] {
font-weight: bold;
display: inline;
}
+#me>div:hover p {
+ color: var(--accent);
+}
+#identity_fingerprint {
+ text-align: center;
+ margin-bottom: 0;
+}
#left_panel ul:last-of-type, #msg_log {
flex-grow: 1;
}
@@ -233,6 +249,10 @@ input[type="file"] {
display: flex;
align-items: center;
flex-grow: 1;
+ cursor: pointer;
+}
+#chat_header>div:hover p {
+ color: var(--accent);
}
#chat_header>div>p {
font-weight: bold;
diff --git a/src/frontend/index.html b/src/frontend/index.html
index 3e42a5d..f99b06d 100644
--- a/src/frontend/index.html
+++ b/src/frontend/index.html
@@ -61,6 +61,7 @@
diff --git a/src/frontend/index.js b/src/frontend/index.js
index 2fd139c..b91e83d 100644
--- a/src/frontend/index.js
+++ b/src/frontend/index.js
@@ -1,7 +1,7 @@
"use strict";
const ENTER_KEY_CODE = 13;
-let identity_name = undefined;
+let identityName = undefined;
let socket = null;
let notificationAllowed = false;
let currentSessionId = -1;
@@ -60,7 +60,7 @@ document.getElementById("delete_conversation").onclick = function() {
}
document.getElementById("add_contact").onclick = function() {
socket.send("contact "+currentSessionId+" "+sessionsData.get(currentSessionId).name);
- sessionsData.get(currentSessionId).is_contact = true;
+ sessionsData.get(currentSessionId).isContact = true;
displayHeader();
displaySessions();
}
@@ -78,9 +78,9 @@ document.getElementById("remove_contact").onclick = function() {
button.onclick = function() {
socket.send("uncontact "+currentSessionId);
let session = sessionsData.get(currentSessionId);
- session.is_contact = false;
- session.is_verified = false;
- if (!session.is_online) {
+ session.isContact = false;
+ session.isVerified = false;
+ if (!session.isOnline) {
sessionsData.delete(currentSessionId);
msgHistory.get(currentSessionId).length = 0;
}
@@ -93,7 +93,44 @@ document.getElementById("remove_contact").onclick = function() {
showPopup(mainDiv);
}
document.getElementById("verify").onclick = function() {
- socket.send("fingerprints "+currentSessionId);
+ let session = sessionsData.get(currentSessionId);
+ if (typeof session !== "undefined") {
+ let mainDiv = document.createElement("div");
+ mainDiv.appendChild(generatePopupWarningTitle());
+ let instructions = document.createElement("p");
+ instructions.textContent = "Compare the following fingerprints by a trusted way of communication (such as real life) and be sure they match.";
+ mainDiv.appendChild(instructions);
+ let p_local = document.createElement("p");
+ p_local.textContent = "Local fingerprint:";
+ mainDiv.appendChild(p_local);
+ let pre_local = document.createElement("pre");
+ pre_local.textContent = beautifyFingerprint(identityFingerprint);
+ mainDiv.appendChild(pre_local);
+ let p_peer = document.createElement("p");
+ p_peer.textContent = "Peer fingerprint:";
+ mainDiv.appendChild(p_peer);
+ let pre_peer = document.createElement("pre");
+ pre_peer.textContent = beautifyFingerprint(session.fingerprint);
+ mainDiv.appendChild(pre_peer);
+ let buttonRow = document.createElement("div");
+ buttonRow.classList.add("button_row");
+ let verifyButton = document.createElement("button");
+ verifyButton.textContent = "They match";
+ verifyButton.onclick = function() {
+ socket.send("verify "+currentSessionId);
+ sessionsData.get(currentSessionId).isVerified = true;
+ removePopup();
+ displayHeader();
+ displaySessions();
+ };
+ buttonRow.appendChild(verifyButton);
+ let cancelButton = document.createElement("button");
+ cancelButton.textContent = "They don't match";
+ cancelButton.onclick = removePopup;
+ buttonRow.appendChild(cancelButton);
+ mainDiv.appendChild(buttonRow);
+ showPopup(mainDiv);
+ }
}
document.getElementById("logout").onclick = function() {
let mainDiv = document.createElement("div");
@@ -141,125 +178,9 @@ document.getElementById("attach_file").onchange = function(event) {
document.getElementById("file_cancel").onclick = function() {
socket.send("abort "+currentSessionId);
}
-
-//source: https://stackoverflow.com/a/14919494
-function humanFileSize(bytes, dp=1) {
- const thresh = 1000;
- if (Math.abs(bytes) < thresh) {
- return bytes + ' B';
- }
- const units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
- let u = -1;
- const r = 10**dp;
- do {
- bytes /= thresh;
- ++u;
- } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
- return bytes.toFixed(dp) + ' ' + units[u];
-}
-//source: https://www.w3schools.com/js/js_cookies.asp
-function getCookie(cname) {
- var name = cname + "=";
- var decodedCookie = decodeURIComponent(document.cookie);
- var ca = decodedCookie.split(';');
- for(var i = 0; i div");
profile_div.onclick = function() {
let mainDiv = document.createElement("div");
- let avatar = generateAvatar(identity_name);
+ let avatar = generateAvatar(identityName);
mainDiv.appendChild(avatar);
+ let fingerprint = document.createElement("pre");
+ fingerprint.id = "identity_fingerprint";
+ fingerprint.textContent = beautifyFingerprint(identityFingerprint);
+ mainDiv.appendChild(fingerprint);
let sectionName = document.createElement("section");
sectionName.textContent = "Name:";
let inputName = document.createElement("input");
inputName.id = "new_name";
inputName.type = "text";
- inputName.value = identity_name;
+ inputName.value = identityName;
sectionName.appendChild(inputName);
let saveNameButton = document.createElement("button");
saveNameButton.textContent = "Save";
@@ -370,21 +295,167 @@ profile_div.onclick = function() {
mainDiv.appendChild(sectionDelete);
showPopup(mainDiv);
}
+let chatHeader = document.getElementById("chat_header");
+chatHeader.children[0].onclick = function() {
+ let session = sessionsData.get(currentSessionId);
+ if (typeof session !== "undefined") {
+ let mainDiv = document.createElement("div");
+ mainDiv.classList.add("session_info");
+ mainDiv.appendChild(generateAvatar(session.name));
+ let h2 = document.createElement("h2");
+ h2.textContent = session.name;
+ mainDiv.appendChild(h2);
+ let pFingerprint = document.createElement("p");
+ pFingerprint.textContent = "Fingerprint:";
+ mainDiv.appendChild(pFingerprint);
+ let pre = document.createElement("pre");
+ pre.textContent = ' '+beautifyFingerprint(session.fingerprint);
+ mainDiv.appendChild(pre);
+ if (session.isOnline) {
+ let pIp = document.createElement("p");
+ pIp.textContent = "IP: "+session.ip;
+ mainDiv.appendChild(pIp);
+ let pConnection = document.createElement("p");
+ pConnection.textContent = "Connection: ";
+ if (session.outgoing) {
+ pConnection.textContent += "outgoing";
+ } else {
+ pConnection.textContent += "incomming";
+ }
+ mainDiv.appendChild(pConnection);
+ }
+ showPopup(mainDiv);
+ }
+}
document.querySelector("#refresher button").onclick = function() {
socket.send("refresh");
}
-function onNewSession(sessionId, outgoing, name) {
+//source: https://stackoverflow.com/a/14919494
+function humanFileSize(bytes, dp=1) {
+ const thresh = 1000;
+ if (Math.abs(bytes) < thresh) {
+ return bytes + ' B';
+ }
+ const units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+ let u = -1;
+ const r = 10**dp;
+ do {
+ bytes /= thresh;
+ ++u;
+ } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
+ return bytes.toFixed(dp) + ' ' + units[u];
+}
+//source: https://www.w3schools.com/js/js_cookies.asp
+function getCookie(cname) {
+ var name = cname + "=";
+ var decodedCookie = decodeURIComponent(document.cookie);
+ var ca = decodedCookie.split(';');
+ for(var i = 0; i {
let name;
if (entry[0]) { //outgoing msg
- name = identity_name;
+ name = identityName;
} else {
name = sessionsData.get(currentSessionId).name;
}
diff --git a/src/main.rs b/src/main.rs
index 8c543ee..517bbe2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -93,16 +93,25 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc 0 {
- ui_connection.set_not_seen(not_seen);
+ {
+ let not_seen = session_manager.not_seen.read().unwrap();
+ if not_seen.len() > 0 {
+ ui_connection.set_not_seen(not_seen.clone());
+ }
}
session_manager.get_saved_msgs().into_iter().for_each(|msgs| {
ui_connection.load_msgs(&msgs.0, &msgs.1);
@@ -181,13 +190,6 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc print_error!(e)
}
}
- "fingerprints" => {
- let session_id: usize = args[1].parse().unwrap();
- let (local, peer) = session_manager.get_public_keys(&session_id);
- let local = crypto::generate_fingerprint(&local);
- let peer = crypto::generate_fingerprint(&peer);
- ui_connection.fingerprints(&local, &peer);
- }
"verify" => {
let session_id: usize = args[1].parse().unwrap();
match session_manager.set_verified(&session_id) {
@@ -509,9 +511,11 @@ fn index_not_logged_in(global_vars: &Arc>) -> HttpResponse {
async fn handle_index(req: HttpRequest) -> HttpResponse {
let global_vars = req.app_data::>>>().unwrap();
if is_authenticated(&req) {
+ let global_vars_read = global_vars.read().unwrap();
HttpResponse::Ok().body(
include_str!("frontend/index.html")
- .replace("WEBSOCKET_PORT", &global_vars.read().unwrap().websocket_port.to_string())
+ .replace("IDENTITY_FINGERPRINT", &crypto::generate_fingerprint(&global_vars_read.session_manager.get_my_public_key()))
+ .replace("WEBSOCKET_PORT", &global_vars_read.websocket_port.to_string())
.replace("IS_IDENTITY_PROTECTED", &Identity::is_protected().unwrap().to_string())
)
} else {
diff --git a/src/session_manager/mod.rs b/src/session_manager/mod.rs
index 4672a0f..4eae0cc 100644
--- a/src/session_manager/mod.rs
+++ b/src/session_manager/mod.rs
@@ -9,7 +9,7 @@ use session::Session;
use ed25519_dalek::PUBLIC_KEY_LENGTH;
use uuid::Uuid;
use platform_dirs::UserDirs;
-use crate::{constants, discovery, identity::{Contact, Identity}, utils::{get_unix_timestamp, get_not_used_path}, print_error};
+use crate::{constants, crypto, discovery, identity::{Contact, Identity}, print_error, utils::{get_unix_timestamp, get_not_used_path}};
use crate::ui_interface::UiConnection;
#[derive(Display, Debug, PartialEq, Eq)]
@@ -19,7 +19,7 @@ pub enum SessionError {
TransmissionCorrupted,
BufferTooLarge,
InvalidSessionId,
- Unknown
+ Unknown,
}
enum SessionCommand {
@@ -55,7 +55,8 @@ pub struct LargeFileDownload {
pub struct SessionData {
pub name: String,
pub outgoing: bool,
- peer_public_key: [u8; PUBLIC_KEY_LENGTH],
+ pub peer_public_key: [u8; PUBLIC_KEY_LENGTH],
+ pub ip: IpAddr,
sender: Sender,
pub file_download: Option,
}
@@ -68,7 +69,7 @@ pub struct SessionManager {
loaded_contacts: RwLock>,
pub last_loaded_msg_offsets: RwLock>,
pub saved_msgs: Mutex)>>>,
- not_seen: RwLock>,
+ pub not_seen: RwLock>,
mdns_service: Mutex