Calls: Indicate whether OMEMO key is verified
This commit is contained in:
parent
8044b546d0
commit
90f9ecf62b
|
@ -29,6 +29,16 @@ public interface EncryptionListEntry : Object {
|
||||||
public abstract Object? get_encryption_icon(Entities.Conversation conversation, ContentItem content_item);
|
public abstract Object? get_encryption_icon(Entities.Conversation conversation, ContentItem content_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface CallEncryptionEntry : Object {
|
||||||
|
public abstract CallEncryptionWidget? get_widget(Account account, Xmpp.Xep.Jingle.ContentEncryption encryption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CallEncryptionWidget : Object {
|
||||||
|
public abstract string? get_title();
|
||||||
|
public abstract bool show_keys();
|
||||||
|
public abstract string? get_icon_name();
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class AccountSettingsEntry : Object {
|
public abstract class AccountSettingsEntry : Object {
|
||||||
public abstract string id { get; }
|
public abstract string id { get; }
|
||||||
public virtual Priority priority { get { return Priority.DEFAULT; } }
|
public virtual Priority priority { get { return Priority.DEFAULT; } }
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Dino.Plugins {
|
||||||
|
|
||||||
public class Registry {
|
public class Registry {
|
||||||
internal ArrayList<EncryptionListEntry> encryption_list_entries = new ArrayList<EncryptionListEntry>();
|
internal ArrayList<EncryptionListEntry> encryption_list_entries = new ArrayList<EncryptionListEntry>();
|
||||||
|
internal HashMap<string, CallEncryptionEntry> call_encryption_entries = new HashMap<string, CallEncryptionEntry>();
|
||||||
internal ArrayList<AccountSettingsEntry> account_settings_entries = new ArrayList<AccountSettingsEntry>();
|
internal ArrayList<AccountSettingsEntry> account_settings_entries = new ArrayList<AccountSettingsEntry>();
|
||||||
internal ArrayList<ContactDetailsProvider> contact_details_entries = new ArrayList<ContactDetailsProvider>();
|
internal ArrayList<ContactDetailsProvider> contact_details_entries = new ArrayList<ContactDetailsProvider>();
|
||||||
internal Map<string, TextCommand> text_commands = new HashMap<string, TextCommand>();
|
internal Map<string, TextCommand> text_commands = new HashMap<string, TextCommand>();
|
||||||
|
@ -25,6 +26,13 @@ public class Registry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool register_call_entryption_entry(string ns, CallEncryptionEntry entry) {
|
||||||
|
lock (call_encryption_entries) {
|
||||||
|
call_encryption_entries[ns] = entry;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public bool register_account_settings_entry(AccountSettingsEntry entry) {
|
public bool register_account_settings_entry(AccountSettingsEntry entry) {
|
||||||
lock(account_settings_entries) {
|
lock(account_settings_entries) {
|
||||||
foreach(var e in account_settings_entries) {
|
foreach(var e in account_settings_entries) {
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace Dino {
|
||||||
call.account = conversation.account;
|
call.account = conversation.account;
|
||||||
call.counterpart = conversation.counterpart;
|
call.counterpart = conversation.counterpart;
|
||||||
call.ourpart = conversation.account.full_jid;
|
call.ourpart = conversation.account.full_jid;
|
||||||
call.time = call.local_time = new DateTime.now_utc();
|
call.time = call.local_time = call.end_time = new DateTime.now_utc();
|
||||||
call.state = Call.State.RINGING;
|
call.state = Call.State.RINGING;
|
||||||
|
|
||||||
stream_interactor.get_module(CallStore.IDENTITY).add_call(call, conversation);
|
stream_interactor.get_module(CallStore.IDENTITY).add_call(call, conversation);
|
||||||
|
@ -380,7 +380,7 @@ namespace Dino {
|
||||||
call.counterpart = from;
|
call.counterpart = from;
|
||||||
}
|
}
|
||||||
call.account = account;
|
call.account = account;
|
||||||
call.time = call.local_time = new DateTime.now_utc();
|
call.time = call.local_time = call.end_time = new DateTime.now_utc();
|
||||||
call.state = Call.State.RINGING;
|
call.state = Call.State.RINGING;
|
||||||
|
|
||||||
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(call.counterpart.bare_jid, account, Conversation.Type.CHAT);
|
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(call.counterpart.bare_jid, account, Conversation.Type.CHAT);
|
||||||
|
|
|
@ -139,6 +139,7 @@ SOURCES
|
||||||
|
|
||||||
src/ui/call_window/audio_settings_popover.vala
|
src/ui/call_window/audio_settings_popover.vala
|
||||||
src/ui/call_window/call_bottom_bar.vala
|
src/ui/call_window/call_bottom_bar.vala
|
||||||
|
src/ui/call_window/call_encryption_button.vala
|
||||||
src/ui/call_window/call_window.vala
|
src/ui/call_window/call_window.vala
|
||||||
src/ui/call_window/call_window_controller.vala
|
src/ui/call_window/call_window_controller.vala
|
||||||
src/ui/call_window/video_settings_popover.vala
|
src/ui/call_window/video_settings_popover.vala
|
||||||
|
|
|
@ -25,8 +25,7 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
||||||
private MenuButton video_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
|
private MenuButton video_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
|
||||||
public VideoSettingsPopover? video_settings_popover;
|
public VideoSettingsPopover? video_settings_popover;
|
||||||
|
|
||||||
private MenuButton encryption_button = new MenuButton() { relief=ReliefStyle.NONE, height_request=30, width_request=30, margin_start=20, margin_bottom=25, halign=Align.START, valign=Align.END };
|
public CallEntryptionButton encryption_button = new CallEntryptionButton() { relief=ReliefStyle.NONE, height_request=30, width_request=30, margin_start=20, margin_bottom=25, halign=Align.START, valign=Align.END };
|
||||||
private Image encryption_image = new Image.from_icon_name("changes-allow-symbolic", IconSize.BUTTON) { visible=true };
|
|
||||||
|
|
||||||
private Label label = new Label("") { margin=20, halign=Align.CENTER, valign=Align.CENTER, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true, visible=true };
|
private Label label = new Label("") { margin=20, halign=Align.CENTER, valign=Align.CENTER, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true, visible=true };
|
||||||
private Stack stack = new Stack() { visible=true };
|
private Stack stack = new Stack() { visible=true };
|
||||||
|
@ -35,8 +34,6 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
||||||
Object(orientation:Orientation.HORIZONTAL, spacing:0);
|
Object(orientation:Orientation.HORIZONTAL, spacing:0);
|
||||||
|
|
||||||
Overlay default_control = new Overlay() { visible=true };
|
Overlay default_control = new Overlay() { visible=true };
|
||||||
encryption_button.add(encryption_image);
|
|
||||||
encryption_button.get_style_context().add_class("encryption-box");
|
|
||||||
default_control.add_overlay(encryption_button);
|
default_control.add_overlay(encryption_button);
|
||||||
|
|
||||||
Box main_buttons = new Box(Orientation.HORIZONTAL, 20) { margin_start=40, margin_end=40, margin=20, halign=Align.CENTER, hexpand=true, visible=true };
|
Box main_buttons = new Box(Orientation.HORIZONTAL, 20) { margin_start=40, margin_end=40, margin=20, halign=Align.CENTER, hexpand=true, visible=true };
|
||||||
|
@ -89,54 +86,6 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
||||||
this.get_style_context().add_class("call-bottom-bar");
|
this.get_style_context().add_class("call-bottom-bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_encryption(Xmpp.Xep.Jingle.ContentEncryption? audio_encryption, Xmpp.Xep.Jingle.ContentEncryption? video_encryption, bool same) {
|
|
||||||
encryption_button.visible = true;
|
|
||||||
|
|
||||||
Popover popover = new Popover(encryption_button);
|
|
||||||
if (audio_encryption == null) {
|
|
||||||
encryption_image.set_from_icon_name("changes-allow-symbolic", IconSize.BUTTON);
|
|
||||||
encryption_button.get_style_context().add_class("unencrypted");
|
|
||||||
|
|
||||||
popover.add(new Label("This call isn't encrypted.") { margin=10, visible=true } );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
encryption_image.set_from_icon_name("changes-prevent-symbolic", IconSize.BUTTON);
|
|
||||||
encryption_button.get_style_context().remove_class("unencrypted");
|
|
||||||
|
|
||||||
Box box = new Box(Orientation.VERTICAL, 5) { margin=10, visible=true };
|
|
||||||
if (audio_encryption.encryption_name == "OMEMO") {
|
|
||||||
box.add(new Label("<b>This call is encrypted with OMEMO.</b>") { use_markup=true, xalign=0, visible=true } );
|
|
||||||
} else {
|
|
||||||
box.add(new Label("<b>This call is end-to-end encrypted.</b>") { use_markup=true, xalign=0, visible=true });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (same) {
|
|
||||||
box.add(create_media_encryption_grid(audio_encryption));
|
|
||||||
} else {
|
|
||||||
box.add(new Label("<b>Audio</b>") { use_markup=true, xalign=0, visible=true });
|
|
||||||
box.add(create_media_encryption_grid(audio_encryption));
|
|
||||||
box.add(new Label("<b>Video</b>") { use_markup=true, xalign=0, visible=true });
|
|
||||||
box.add(create_media_encryption_grid(video_encryption));
|
|
||||||
}
|
|
||||||
popover.add(box);
|
|
||||||
|
|
||||||
encryption_button.set_popover(popover);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Grid create_media_encryption_grid(Xmpp.Xep.Jingle.ContentEncryption? encryption) {
|
|
||||||
Grid ret = new Grid() { row_spacing=3, column_spacing=5, visible=true };
|
|
||||||
if (encryption.peer_key.length > 0) {
|
|
||||||
ret.attach(new Label("Peer call key") { xalign=0, visible=true }, 1, 2, 1, 1);
|
|
||||||
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.peer_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true, visible=true }, 2, 2, 1, 1);
|
|
||||||
}
|
|
||||||
if (encryption.our_key.length > 0) {
|
|
||||||
ret.attach(new Label("Your call key") { xalign=0, visible=true }, 1, 3, 1, 1);
|
|
||||||
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.our_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true, visible=true }, 2, 3, 1, 1);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AudioSettingsPopover? show_audio_device_choices(bool show) {
|
public AudioSettingsPopover? show_audio_device_choices(bool show) {
|
||||||
audio_settings_button.visible = show;
|
audio_settings_button.visible = show;
|
||||||
if (audio_settings_popover != null) audio_settings_popover.visible = false;
|
if (audio_settings_popover != null) audio_settings_popover.visible = false;
|
||||||
|
@ -212,15 +161,4 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
||||||
public bool is_menu_active() {
|
public bool is_menu_active() {
|
||||||
return video_settings_button.active || audio_settings_button.active || encryption_button.active;
|
return video_settings_button.active || audio_settings_button.active || encryption_button.active;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string format_fingerprint(uint8[] fingerprint) {
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
for (int i = 0; i < fingerprint.length; i++) {
|
|
||||||
sb.append("%02x".printf(fingerprint[i]));
|
|
||||||
if (i < fingerprint.length - 1) {
|
|
||||||
sb.append(":");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.str;
|
|
||||||
}
|
|
||||||
}
|
}
|
77
main/src/ui/call_window/call_encryption_button.vala
Normal file
77
main/src/ui/call_window/call_encryption_button.vala
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
using Dino.Entities;
|
||||||
|
using Gtk;
|
||||||
|
using Pango;
|
||||||
|
|
||||||
|
public class Dino.Ui.CallEntryptionButton : MenuButton {
|
||||||
|
|
||||||
|
private Image encryption_image = new Image.from_icon_name("changes-allow-symbolic", IconSize.BUTTON) { visible=true };
|
||||||
|
|
||||||
|
construct {
|
||||||
|
add(encryption_image);
|
||||||
|
get_style_context().add_class("encryption-box");
|
||||||
|
this.set_popover(popover);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_icon(bool encrypted, string? icon_name) {
|
||||||
|
this.visible = true;
|
||||||
|
|
||||||
|
if (encrypted) {
|
||||||
|
encryption_image.set_from_icon_name(icon_name ?? "changes-prevent-symbolic", IconSize.BUTTON);
|
||||||
|
get_style_context().remove_class("unencrypted");
|
||||||
|
} else {
|
||||||
|
encryption_image.set_from_icon_name(icon_name ?? "changes-allow-symbolic", IconSize.BUTTON);
|
||||||
|
get_style_context().add_class("unencrypted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_info(string? title, bool show_keys, Xmpp.Xep.Jingle.ContentEncryption? audio_encryption, Xmpp.Xep.Jingle.ContentEncryption? video_encryption) {
|
||||||
|
Popover popover = new Popover(this);
|
||||||
|
this.set_popover(popover);
|
||||||
|
|
||||||
|
if (audio_encryption == null) {
|
||||||
|
popover.add(new Label("This call is unencrypted.") { margin=10, visible=true } );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (title != null && !show_keys) {
|
||||||
|
popover.add(new Label(title) { use_markup=true, margin=10, visible=true } );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Box box = new Box(Orientation.VERTICAL, 10) { margin=10, visible=true };
|
||||||
|
box.add(new Label("<b>%s</b>".printf(title ?? "This call is end-to-end encrypted.")) { use_markup=true, xalign=0, visible=true });
|
||||||
|
|
||||||
|
if (video_encryption == null) {
|
||||||
|
box.add(create_media_encryption_grid(audio_encryption));
|
||||||
|
} else {
|
||||||
|
box.add(new Label("<b>Audio</b>") { use_markup=true, xalign=0, visible=true });
|
||||||
|
box.add(create_media_encryption_grid(audio_encryption));
|
||||||
|
box.add(new Label("<b>Video</b>") { use_markup=true, xalign=0, visible=true });
|
||||||
|
box.add(create_media_encryption_grid(video_encryption));
|
||||||
|
}
|
||||||
|
popover.add(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Grid create_media_encryption_grid(Xmpp.Xep.Jingle.ContentEncryption? encryption) {
|
||||||
|
Grid ret = new Grid() { row_spacing=3, column_spacing=5, visible=true };
|
||||||
|
if (encryption.peer_key.length > 0) {
|
||||||
|
ret.attach(new Label("Peer call key") { xalign=0, visible=true }, 1, 2, 1, 1);
|
||||||
|
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.peer_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true, visible=true }, 2, 2, 1, 1);
|
||||||
|
}
|
||||||
|
if (encryption.our_key.length > 0) {
|
||||||
|
ret.attach(new Label("Your call key") { xalign=0, visible=true }, 1, 3, 1, 1);
|
||||||
|
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.our_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true, visible=true }, 2, 3, 1, 1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string format_fingerprint(uint8[] fingerprint) {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < fingerprint.length; i++) {
|
||||||
|
sb.append("%02x".printf(fingerprint[i]));
|
||||||
|
if (i < fingerprint.length - 1) {
|
||||||
|
sb.append(":");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.str;
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,7 +78,22 @@ public class Dino.Ui.CallWindowController : Object {
|
||||||
});
|
});
|
||||||
calls.encryption_updated.connect((call, audio_encryption, video_encryption, same) => {
|
calls.encryption_updated.connect((call, audio_encryption, video_encryption, same) => {
|
||||||
if (!this.call.equals(call)) return;
|
if (!this.call.equals(call)) return;
|
||||||
call_window.bottom_bar.set_encryption(audio_encryption, video_encryption, same);
|
|
||||||
|
string? title = null;
|
||||||
|
string? icon_name = null;
|
||||||
|
bool show_keys = true;
|
||||||
|
Plugins.Registry registry = Dino.Application.get_default().plugin_registry;
|
||||||
|
Plugins.CallEncryptionEntry? encryption_entry = audio_encryption != null ? registry.call_encryption_entries[audio_encryption.encryption_ns] : null;
|
||||||
|
if (encryption_entry != null) {
|
||||||
|
Plugins.CallEncryptionWidget? encryption_widgets = encryption_entry.get_widget(call.account, audio_encryption);
|
||||||
|
if (encryption_widgets != null) {
|
||||||
|
title = encryption_widgets.get_title();
|
||||||
|
icon_name = encryption_widgets.get_icon_name();
|
||||||
|
show_keys = encryption_widgets.show_keys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call_window.bottom_bar.encryption_button.set_info(title, show_keys, audio_encryption, same ? null :video_encryption);
|
||||||
|
call_window.bottom_bar.encryption_button.set_icon(audio_encryption != null, icon_name);
|
||||||
});
|
});
|
||||||
|
|
||||||
own_video.resolution_changed.connect((width, height) => {
|
own_video.resolution_changed.connect((width, height) => {
|
||||||
|
|
|
@ -55,6 +55,7 @@ SOURCES
|
||||||
src/ui/account_settings_entry.vala
|
src/ui/account_settings_entry.vala
|
||||||
src/ui/account_settings_widget.vala
|
src/ui/account_settings_widget.vala
|
||||||
src/ui/bad_messages_populator.vala
|
src/ui/bad_messages_populator.vala
|
||||||
|
src/ui/call_encryption_entry.vala
|
||||||
src/ui/contact_details_provider.vala
|
src/ui/contact_details_provider.vala
|
||||||
src/ui/contact_details_dialog.vala
|
src/ui/contact_details_dialog.vala
|
||||||
src/ui/device_notification_populator.vala
|
src/ui/device_notification_populator.vala
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace Dino.Plugins.Omemo.DtlsSrtpVerificationDraft {
|
||||||
stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.begin(jingle_sid, (_, res) => {
|
stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.begin(jingle_sid, (_, res) => {
|
||||||
Xep.Jingle.Session? session = stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.end(res);
|
Xep.Jingle.Session? session = stream.get_flag(Xep.Jingle.Flag.IDENTITY).get_session.end(res);
|
||||||
if (session == null || !session.contents_map.has_key(content_name)) return;
|
if (session == null || !session.contents_map.has_key(content_name)) return;
|
||||||
var encryption = new OmemoContentEncryption() { encryption_ns=NS_URI, encryption_name="OMEMO", our_key=new uint8[0], peer_key=new uint8[0], peer_device_id=device_id_by_jingle_sid[jingle_sid] };
|
var encryption = new OmemoContentEncryption() { encryption_ns=NS_URI, encryption_name="OMEMO", our_key=new uint8[0], peer_key=new uint8[0], sid=device_id_by_jingle_sid[jingle_sid], jid=iq.from.bare_jid };
|
||||||
session.contents_map[content_name].encryptions[NS_URI] = encryption;
|
session.contents_map[content_name].encryptions[NS_URI] = encryption;
|
||||||
|
|
||||||
if (iq.stanza.get_deep_attribute(Xep.Jingle.NS_URI + ":jingle", "action") == "session-accept") {
|
if (iq.stanza.get_deep_attribute(Xep.Jingle.NS_URI + ":jingle", "action") == "session-accept") {
|
||||||
|
@ -143,7 +143,7 @@ namespace Dino.Plugins.Omemo.DtlsSrtpVerificationDraft {
|
||||||
|
|
||||||
private void on_content_add_received(XmppStream stream, Xep.Jingle.Content content) {
|
private void on_content_add_received(XmppStream stream, Xep.Jingle.Content content) {
|
||||||
if (!content_names_by_jingle_sid.has_key(content.session.sid) || content_names_by_jingle_sid[content.session.sid].contains(content.content_name)) {
|
if (!content_names_by_jingle_sid.has_key(content.session.sid) || content_names_by_jingle_sid[content.session.sid].contains(content.content_name)) {
|
||||||
var encryption = new OmemoContentEncryption() { encryption_ns=NS_URI, encryption_name="OMEMO", our_key=new uint8[0], peer_key=new uint8[0], peer_device_id=device_id_by_jingle_sid[content.session.sid] };
|
var encryption = new OmemoContentEncryption() { encryption_ns=NS_URI, encryption_name="OMEMO", our_key=new uint8[0], peer_key=new uint8[0], sid=device_id_by_jingle_sid[content.session.sid], jid=content.peer_full_jid.bare_jid };
|
||||||
content.encryptions[encryption.encryption_ns] = encryption;
|
content.encryptions[encryption.encryption_ns] = encryption;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,8 @@ namespace Dino.Plugins.Omemo.DtlsSrtpVerificationDraft {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OmemoContentEncryption : Xep.Jingle.ContentEncryption {
|
public class OmemoContentEncryption : Xep.Jingle.ContentEncryption {
|
||||||
public int peer_device_id { get; set; }
|
public Jid jid { get; set; }
|
||||||
|
public int sid { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,10 @@ namespace Dino.Plugins.Omemo {
|
||||||
message.real_jid = possible_jid;
|
message.real_jid = possible_jid;
|
||||||
}
|
}
|
||||||
|
|
||||||
trust_manager.message_device_id_map[message] = data.sid;
|
|
||||||
message.body = cleartext;
|
message.body = cleartext;
|
||||||
message.encryption = Encryption.OMEMO;
|
message.encryption = Encryption.OMEMO;
|
||||||
|
|
||||||
|
trust_manager.message_device_id_map[message] = data.sid;
|
||||||
return true;
|
return true;
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
debug("Decrypting message from %s/%d failed: %s", possible_jid.to_string(), data.sid, e.message);
|
debug("Decrypting message from %s/%d failed: %s", possible_jid.to_string(), data.sid, e.message);
|
||||||
|
|
|
@ -35,7 +35,6 @@ public class Plugin : RootInterface, Object {
|
||||||
public DeviceNotificationPopulator device_notification_populator;
|
public DeviceNotificationPopulator device_notification_populator;
|
||||||
public OwnNotifications own_notifications;
|
public OwnNotifications own_notifications;
|
||||||
public TrustManager trust_manager;
|
public TrustManager trust_manager;
|
||||||
public DecryptMessageListener decrypt_message_listener;
|
|
||||||
public HashMap<Account, OmemoDecryptor> decryptors = new HashMap<Account, OmemoDecryptor>(Account.hash_func, Account.equals_func);
|
public HashMap<Account, OmemoDecryptor> decryptors = new HashMap<Account, OmemoDecryptor>(Account.hash_func, Account.equals_func);
|
||||||
public HashMap<Account, OmemoEncryptor> encryptors = new HashMap<Account, OmemoEncryptor>(Account.hash_func, Account.equals_func);
|
public HashMap<Account, OmemoEncryptor> encryptors = new HashMap<Account, OmemoEncryptor>(Account.hash_func, Account.equals_func);
|
||||||
|
|
||||||
|
@ -54,6 +53,7 @@ public class Plugin : RootInterface, Object {
|
||||||
this.app.plugin_registry.register_contact_details_entry(contact_details_provider);
|
this.app.plugin_registry.register_contact_details_entry(contact_details_provider);
|
||||||
this.app.plugin_registry.register_notification_populator(device_notification_populator);
|
this.app.plugin_registry.register_notification_populator(device_notification_populator);
|
||||||
this.app.plugin_registry.register_conversation_addition_populator(new BadMessagesPopulator(this.app.stream_interactor, this));
|
this.app.plugin_registry.register_conversation_addition_populator(new BadMessagesPopulator(this.app.stream_interactor, this));
|
||||||
|
this.app.plugin_registry.register_call_entryption_entry(DtlsSrtpVerificationDraft.NS_URI, new CallEncryptionEntry(db));
|
||||||
|
|
||||||
this.app.stream_interactor.module_manager.initialize_account_modules.connect((account, list) => {
|
this.app.stream_interactor.module_manager.initialize_account_modules.connect((account, list) => {
|
||||||
Signal.Store signal_store = Plugin.get_context().create_store();
|
Signal.Store signal_store = Plugin.get_context().create_store();
|
||||||
|
@ -67,9 +67,7 @@ public class Plugin : RootInterface, Object {
|
||||||
this.own_notifications = new OwnNotifications(this, this.app.stream_interactor, account);
|
this.own_notifications = new OwnNotifications(this, this.app.stream_interactor, account);
|
||||||
});
|
});
|
||||||
|
|
||||||
decrypt_message_listener = new DecryptMessageListener(decryptors);
|
app.stream_interactor.get_module(MessageProcessor.IDENTITY).received_pipeline.connect(new DecryptMessageListener(decryptors));
|
||||||
app.stream_interactor.get_module(MessageProcessor.IDENTITY).received_pipeline.connect(decrypt_message_listener);
|
|
||||||
|
|
||||||
app.stream_interactor.get_module(FileManager.IDENTITY).add_file_decryptor(new OmemoFileDecryptor());
|
app.stream_interactor.get_module(FileManager.IDENTITY).add_file_decryptor(new OmemoFileDecryptor());
|
||||||
app.stream_interactor.get_module(FileManager.IDENTITY).add_file_encryptor(new OmemoFileEncryptor());
|
app.stream_interactor.get_module(FileManager.IDENTITY).add_file_encryptor(new OmemoFileEncryptor());
|
||||||
JingleFileHelperRegistry.instance.add_encryption_helper(Encryption.OMEMO, new JetOmemo.EncryptionHelper(app.stream_interactor));
|
JingleFileHelperRegistry.instance.add_encryption_helper(Encryption.OMEMO, new JetOmemo.EncryptionHelper(app.stream_interactor));
|
||||||
|
|
57
plugins/omemo/src/ui/call_encryption_entry.vala
Normal file
57
plugins/omemo/src/ui/call_encryption_entry.vala
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
using Dino.Entities;
|
||||||
|
using Gtk;
|
||||||
|
using Qlite;
|
||||||
|
using Xmpp;
|
||||||
|
|
||||||
|
namespace Dino.Plugins.Omemo {
|
||||||
|
|
||||||
|
public class CallEncryptionEntry : Plugins.CallEncryptionEntry, Object {
|
||||||
|
private Database db;
|
||||||
|
|
||||||
|
public CallEncryptionEntry(Database db) {
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plugins.CallEncryptionWidget? get_widget(Account account, Xmpp.Xep.Jingle.ContentEncryption encryption) {
|
||||||
|
DtlsSrtpVerificationDraft.OmemoContentEncryption? omemo_encryption = encryption as DtlsSrtpVerificationDraft.OmemoContentEncryption;
|
||||||
|
if (omemo_encryption == null) return null;
|
||||||
|
|
||||||
|
int identity_id = db.identity.get_id(account.id);
|
||||||
|
Row? device = db.identity_meta.get_device(identity_id, omemo_encryption.jid.to_string(), omemo_encryption.sid);
|
||||||
|
if (device == null) return null;
|
||||||
|
TrustLevel trust = (TrustLevel) device[db.identity_meta.trust_level];
|
||||||
|
|
||||||
|
return new CallEncryptionWidget(trust);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CallEncryptionWidget : Plugins.CallEncryptionWidget, Object {
|
||||||
|
|
||||||
|
string? title = null;
|
||||||
|
string? icon = null;
|
||||||
|
bool should_show_keys = false;
|
||||||
|
|
||||||
|
public CallEncryptionWidget(TrustLevel trust) {
|
||||||
|
if (trust == TrustLevel.VERIFIED) {
|
||||||
|
title = "This call is <b>encrypted and verified</b> with OMEMO.";
|
||||||
|
icon = "dino-security-high-symbolic";
|
||||||
|
should_show_keys = false;
|
||||||
|
} else {
|
||||||
|
title = "This call is encrypted with OMEMO.";
|
||||||
|
should_show_keys = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? get_title() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? get_icon_name() {
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool show_keys() {
|
||||||
|
return should_show_keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue