1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
using Gtk;
using Qlite;
namespace Dino.Plugins.Omemo {
[GtkTemplate (ui = "/im/dino/Dino/omemo/manage_key_dialog.ui")]
public class ManageKeyDialog : Gtk.Dialog {
[GtkChild] private Stack manage_stack;
[GtkChild] private Button cancel_button;
[GtkChild] private Button ok_button;
[GtkChild] private Box main_screen;
[GtkChild] private Label main_desc_label;
[GtkChild] private ListBox main_action_list;
[GtkChild] private Box confirm_screen;
[GtkChild] private Image confirm_image;
[GtkChild] private Label confirm_title_label;
[GtkChild] private Label confirm_desc_label;
[GtkChild] private Box verify_screen;
[GtkChild] private Label verify_label;
[GtkChild] private Button verify_yes_button;
[GtkChild] private Button verify_no_button;
private Row device;
private Database db;
private bool return_to_main;
private int current_response;
public ManageKeyDialog(Row device, Database db) {
Object(use_header_bar : 1);
this.device = device;
this.db = db;
setup_main_screen();
setup_verify_screen();
cancel_button.clicked.connect(handle_cancel);
ok_button.clicked.connect(() => {
response(current_response);
close();
});
verify_yes_button.clicked.connect(() => {
confirm_image.set_from_icon_name("security-high-symbolic", IconSize.DIALOG);
confirm_title_label.label = "Verify key";
confirm_desc_label.set_markup(@"Once confirmed, any future messages sent by <b>$(device[db.identity_meta.address_name])</b> using this key will be highlighted accordingly in the chat window.");
manage_stack.set_visible_child_name("confirm");
ok_button.sensitive = true;
return_to_main = false;
current_response = Database.IdentityMetaTable.TrustLevel.VERIFIED;
});
verify_no_button.clicked.connect(() => {
return_to_main = false;
confirm_image.set_from_icon_name("dialog-warning-symbolic", IconSize.DIALOG);
confirm_title_label.label = "Fingerprints do not match";
confirm_desc_label.set_markup(@"Please verify that you are comparing the correct fingerprint. If fingerprints do not match <b>$(device[db.identity_meta.address_name])</b>'s account may be compromised and you should consider rejecting this key.");
manage_stack.set_visible_child_name("confirm");
});
}
private void handle_cancel() {
if (manage_stack.get_visible_child_name() == "main") close();
if (manage_stack.get_visible_child_name() == "verify") {
manage_stack.set_visible_child_name("main");
cancel_button.label = "Cancel";
}
if (manage_stack.get_visible_child_name() == "confirm") {
if (return_to_main) {
manage_stack.set_visible_child_name("main");
cancel_button.label = "Cancel";
} else {
manage_stack.set_visible_child_name("verify");
}
}
ok_button.sensitive = false;
}
private Box make_action_box(string title, string desc){
Box box = new Box(Orientation.VERTICAL, 0) { visible = true, margin_start = 20, margin_end = 20, margin_top = 14, margin_bottom = 14 };
Label lbl_title = new Label(title) { visible = true, halign = Align.START };
Label lbl_desc = new Label(desc) { visible = true, xalign = 0, wrap = true, max_width_chars = 40 };
Pango.AttrList title_attrs = new Pango.AttrList();
title_attrs.insert(Pango.attr_scale_new(1.1));
lbl_title.attributes = title_attrs;
Pango.AttrList desc_attrs = new Pango.AttrList();
desc_attrs.insert(Pango.attr_scale_new(0.8));
lbl_desc.attributes = desc_attrs;
lbl_desc.get_style_context().add_class("dim-label");
box.add(lbl_title);
box.add(lbl_desc);
return box;
}
private Box make_trust_screen(string icon_name, string title, string desc) {
Box box = new Box(Orientation.VERTICAL, 12) { margin = 12, spacing = 12 };
Image icon = new Image.from_icon_name(icon_name, IconSize.DIALOG) { visible = true };
box.add(icon);
Label lbl_title = new Label(title) { visible = true };
Label lbl_desc = new Label(desc) { visible = true, use_markup = true, max_width_chars = 1, wrap = true, justify = Justification.CENTER };
Pango.AttrList title_attrs = new Pango.AttrList();
title_attrs.insert(Pango.attr_scale_new(1.1));
lbl_title.attributes = title_attrs;
Pango.AttrList desc_attrs = new Pango.AttrList();
desc_attrs.insert(Pango.attr_scale_new(0.8));
lbl_desc.attributes = desc_attrs;
lbl_desc.get_style_context().add_class("dim-label");
box.add(lbl_title);
box.add(lbl_desc);
return box;
}
private void setup_main_screen() {
main_action_list.set_header_func((row, before_row) => {
if (row.get_header() == null && before_row != null) {
row.set_header(new Separator(Orientation.HORIZONTAL));
}
});
ListBoxRow verify_row = new ListBoxRow() { visible = true };
verify_row.add(make_action_box("Verify Key Fingerprint", "Compare this key's fingerprint with the fingerprint displayed on the contact's device."));
ListBoxRow reject_row = new ListBoxRow() { visible = true };
reject_row.add(make_action_box("Reject Key", "Stop accepting this key during communication with its associated contact."));
ListBoxRow accept_row = new ListBoxRow() {visible = true };
accept_row.add(make_action_box("Accept Key", "Start accepting this key during communication with its assoicated contact"));
switch((Database.IdentityMetaTable.TrustLevel) device[db.identity_meta.trust_level]) {
case Database.IdentityMetaTable.TrustLevel.TRUSTED:
main_desc_label.set_markup(@"This key is currently <span color='#1A63D9'>accepted</span>. This means it can be used by <b>$(device[db.identity_meta.address_name])</b> to receive and send messages.");
main_action_list.add(verify_row);
main_action_list.add(reject_row);
break;
case Database.IdentityMetaTable.TrustLevel.VERIFIED:
main_desc_label.set_markup(@"This key is currently <span color='#1A63D9'>verified</span>. This means it can be used by <b>$(device[db.identity_meta.address_name])</b> to receive and send messages. Additionaly it has been verified out-of-band to match the key on the contact's device.");
main_action_list.add(reject_row);
break;
case Database.IdentityMetaTable.TrustLevel.UNTRUSTED:
main_desc_label.set_markup(@"This key is currently <span color='#D91900'>rejected</span>. This means it cannot be used by <b>$(device[db.identity_meta.address_name])</b> to receive messages, and any messages sent by it will be ignored");
main_action_list.add(accept_row);
break;
}
//Row clicked - go to appropriate screen
main_action_list.row_activated.connect((row) => {
if(row == verify_row) {
manage_stack.set_visible_child_name("verify");
} else if (row == reject_row) {
confirm_image.set_from_icon_name("action-unavailable-symbolic", IconSize.DIALOG);
confirm_title_label.label = "Reject key";
confirm_desc_label.set_markup(@"Once confirmed, any future messages sent by <b>$(device[db.identity_meta.address_name])</b> using this key will be ignored and none of your messages will be readable using this key.");
manage_stack.set_visible_child_name("confirm");
ok_button.sensitive = true;
return_to_main = true;
current_response = Database.IdentityMetaTable.TrustLevel.UNTRUSTED;
} else if (row == accept_row) {
confirm_image.set_from_icon_name("emblem-ok-symbolic", IconSize.DIALOG);
confirm_title_label.label = "Accept key";
confirm_desc_label.set_markup(@"Once confirmed this key will be usable by <b>$(device[db.identity_meta.address_name])</b> to receive and send messages.");
manage_stack.set_visible_child_name("confirm");
ok_button.sensitive = true;
return_to_main = true;
current_response = Database.IdentityMetaTable.TrustLevel.TRUSTED;
}
cancel_button.label = "Back";
});
manage_stack.set_visible_child_name("main");
}
private void setup_verify_screen() {
verify_label.set_markup(fingerprint_markup(fingerprint_from_base64(device[db.identity_meta.identity_key_public_base64])));
}
}
}
|