aboutsummaryrefslogtreecommitdiff
path: root/plugins/omemo/src/ui/manage_key_dialog.vala
blob: a4b61f706cd09470b11e723276464c5e64cc124f (plain) (blame)
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
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 unowned HeaderBar headerbar;
    [GtkChild] private unowned Stack manage_stack;

    [GtkChild] private unowned Button cancel_button;
    [GtkChild] private unowned Button ok_button;

    [GtkChild] private unowned Label main_desc_label;
    [GtkChild] private unowned ListBox main_action_list;

    [GtkChild] private unowned Image confirm_image;
    [GtkChild] private unowned Label confirm_title_label;
    [GtkChild] private unowned Label confirm_desc_label;

    [GtkChild] private unowned Label verify_label;
    [GtkChild] private unowned Label compare_fingerprint_label;
    [GtkChild] private unowned Button verify_yes_button;
    [GtkChild] private unowned Button verify_no_button;

    private Row device;
    private Database db;

    private bool return_to_main;
    private int current_response;

    construct {
        // If we set the strings in the .ui file, they don't get translated
        this.title = _("Manage Key");
        compare_fingerprint_label.label = _("Compare the fingerprint, character by character, with the one shown on your contact's device.");
        verify_no_button.label = _("Fingerprints differ");
        verify_yes_button.label = _("Fingerprints match");
        cancel_button.label = _("Cancel");
        ok_button.label = _("Confirm");
    }

    public ManageKeyDialog(Row device, Database db) {
        Object(use_header_bar : Environment.get_variable("GTK_CSD") != "0" ? 1 : 0);

        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");
            confirm_title_label.label = _("Verify key");
            confirm_desc_label.set_markup(_("Future messages sent by %s from the device that uses this key will be highlighted accordingly in the chat window.").printf(@"<b>$(device[db.identity_meta.address_name])</b>"));
            manage_stack.set_visible_child_name("confirm");
            ok_button.sensitive = true;
            return_to_main = false;
            current_response = TrustLevel.VERIFIED;
        });

        verify_no_button.clicked.connect(() => {
            return_to_main = false;
            confirm_image.set_from_icon_name("dialog-warning-symbolic");
            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, %s's account may be compromised and you should consider rejecting this key.").printf(@"<b>$(device[db.identity_meta.address_name])</b>"));
            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.append(lbl_title);
        box.append(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.set_child(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.set_child(make_action_box(_("Reject key"), _("Block encrypted communication with the contact's device that uses this key.")));
        ListBoxRow accept_row = new ListBoxRow() {visible = true };
        accept_row.set_child(make_action_box(_("Accept key"), _("Allow encrypted communication with the contact's device that uses this key.")));

        switch((TrustLevel) device[db.identity_meta.trust_level]) {
            case TrustLevel.TRUSTED:
                main_desc_label.set_markup(_("This key is currently %s.").printf("<span color='#1A63D9'>"+_("accepted")+"</span>")+" "+_("This means it can be used by %s to receive and send encrypted messages.").printf(@"<b>$(device[db.identity_meta.address_name])</b>"));
                main_action_list.append(verify_row);
                main_action_list.append(reject_row);
                break;
            case TrustLevel.VERIFIED:
                main_desc_label.set_markup(_("This key is currently %s.").printf("<span color='#1A63D9'>"+_("verified")+"</span>")+" "+_("This means it can be used by %s to receive and send encrypted messages.").printf(@"<b>$(device[db.identity_meta.address_name])</b>") + " " + _("Additionally it has been verified to match the key on the contact's device."));
                main_action_list.append(reject_row);
                break;
            case TrustLevel.UNTRUSTED:
                main_desc_label.set_markup(_("This key is currently %s.").printf("<span color='#D91900'>"+_("rejected")+"</span>")+" "+_("This means it cannot be used by %s to decipher your messages, and you won't see messages encrypted with it.").printf(@"<b>$(device[db.identity_meta.address_name])</b>"));
                main_action_list.append(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");
                confirm_title_label.label = _("Reject key");
                confirm_desc_label.set_markup(_("You won't see encrypted messages from the device of %s that uses this key. Conversely, that device won't be able to decipher your messages anymore.").printf(@"<b>$(device[db.identity_meta.address_name])</b>"));
                manage_stack.set_visible_child_name("confirm");
                ok_button.sensitive = true;
                return_to_main = true;
                current_response = TrustLevel.UNTRUSTED;
            } else if (row == accept_row) {
                confirm_image.set_from_icon_name("emblem-ok-symbolic");
                confirm_title_label.label = _("Accept key");
                confirm_desc_label.set_markup(_("You will be able to exchange encrypted messages with the device of %s that uses this key.").printf(@"<b>$(device[db.identity_meta.address_name])</b>"));
                manage_stack.set_visible_child_name("confirm");
                ok_button.sensitive = true;
                return_to_main = true;
                current_response = 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])));
    }
}

}