1 /* Configure dialog UI */
2 /* Copyright (C) 2001-2003 William Tompkins */
3
4 /* This plugin is free software, distributed under the GNU General Public */
5 /* License. */
6 /* Please see the file "COPYING" distributed with this source code */
7 /* for more details */
8 /* */
9 /* */
10 /* This software is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
13 /* General Public License for more details. */
14
15 /* To compile and use: */
16 /* See INSTALL file. */
17
18 #include "internal.h"
19
20 #include <string.h>
21 #include <assert.h>
22
23 #include <gdk/gdk.h>
24 #include <gtk/gtk.h>
25 #include <gtk/gtkplug.h>
26
27 #include <debug.h>
28 #include <gtkdialogs.h>
29 #include <gtkprefs.h>
30 #include <gtkprefs.h>
31 #include <util.h>
32
zip(T0 const & t0,T1 const & t1)33 #include "nls.h"
34 #include "cryptproto.h"
35 #include "keys.h"
36 #include "config_ui.h"
37
38 #ifdef _WIN32
39 #include "win32dep.h"
40 #endif
41
42 /*Static vars for the config dialog: */
43 static GtkWidget *key_size_entry, *proto_combo;
44
45 /* static GtkListStore *key_list_store = NULL; */
46 /* static GtkWidget *key_list_view = NULL; */
47
48 static GtkWidget *regen_err_label;
49 static GtkWidget *regen_window = NULL; /* regenerate key popup */
50
51 static GtkWidget* config_vbox = NULL; /* Our main config pane */
52 static GtkWidget* Local_keylist_view = NULL;
53 static GtkWidget* Saved_keylist_view = NULL;
54 static GtkWidget* InMem_keylist_view = NULL;
zip(T0 const & t0,T1 const & t1,T2 const & t2)55
56 static GtkWidget* Invalid_path_label = NULL;
57 static GtkWidget* Invalid_path_button = NULL;
58
59 static void create_key_files_cb();
60
61 /* Callbacks for the Regenerate popup dialog */
62 static void config_cancel_regen() {
63 if (regen_window) {
64 gtk_widget_destroy(regen_window);
65 }
66 regen_window = NULL;
67 }
68
69 static void config_do_regen(GtkWidget* hitbutton, GtkWidget *key_list_view) {
70 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(key_list_view));
71 GtkListStore *key_list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(key_list_view)));
72
73 const gchar* bits_string = gtk_entry_get_text(GTK_ENTRY(key_size_entry));
74 const gchar* proto_string =
75 gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(proto_combo)->entry)); // should NOT be freed
76 int bits = 0;
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3)77 GSList *proto = crypt_proto_list;
78 gchar *name;
79 PurpleAccount *acct;
80 gchar key_len[15];
81
82 GString *key_buf;
83 GtkTreeIter list_store_iter;
84
85 sscanf(bits_string, "%d", &bits);
86
87 if (bits == 0) {
88 gtk_label_set_text(GTK_LABEL(regen_err_label),
89 _("Bad key size"));
90 return;
91 }
92
93 if (bits < 512) {
94 gtk_label_set_text(GTK_LABEL(regen_err_label),
95 _("Keys < 512 bits are VERY insecure"));
96 return;
97 }
98
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4)99 if (bits > 4096) {
100 gtk_label_set_text(GTK_LABEL(regen_err_label),
101 _("Keys > 4096 bits will cause extreme\n"
102 "message bloat, causing problems with\n"
103 "message transmission"));
104 return;
105 }
106
107 while (proto != NULL &&
108 strcmp(proto_string, ((crypt_proto*)proto->data)->name) != 0) {
109 proto = proto->next;
110 }
111
112 if (proto == NULL) {
113 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Can't find protocol in list! Aigh!\n");
114 return;
115 }
116
117 if (gtk_tree_selection_get_selected(selection, NULL, &list_store_iter)) {
118 crypt_key * regenerated_key;
119
120 gtk_tree_model_get(GTK_TREE_MODEL(key_list_store), &list_store_iter, 0, &name, 4, &acct, -1);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5)121 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "regen for name: '%s', acct: %p\n", name, acct);
122
123 PE_make_private_pair((crypt_proto*)proto->data, name, acct, bits);
124
125 snprintf(key_len, sizeof(key_len), "%d", bits);
126
127 regenerated_key = PE_find_key_by_name(PE_my_pub_ring, name, acct);
128 if (regenerated_key) {
129 key_buf = g_string_new_len(regenerated_key->fingerprint, KEY_FINGERPRINT_LENGTH);
130 } else {
131 key_buf = g_string_new("--error--");
132 }
133
134 gtk_list_store_set(key_list_store, &list_store_iter,
135 1, key_len,
136 2, key_buf->str,
137 3, proto_string,
138 -1);
139
140 g_string_free(key_buf, TRUE);
141 g_free(name);
142 }
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6)143
144 config_cancel_regen();
145
146 hitbutton = hitbutton; /* unused */
147 }
148
149 /* Display the Regenerate Key popup, and set up the above callbacks */
150 /* (used as a callback from the main Config dialog, below) */
151 static void config_regen_key(GtkWidget* hitbutton, GtkWidget* key_list_view) {
152 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(key_list_view));
153
154 GtkWidget *vbox, *hbox, *label, *table, *button;
155 GList *proto_list = NULL;
156 key_ring* iter;
157
158 if (regen_window != NULL) return;
159
160 PIDGIN_DIALOG(regen_window);
161 gtk_widget_set_size_request(regen_window, 300, 150);
162 gtk_window_set_title(GTK_WINDOW(regen_window), _("Generate Keys"));
163 g_signal_connect(G_OBJECT(regen_window), "destroy",
164 GTK_SIGNAL_FUNC(config_cancel_regen), NULL);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7)165
166 vbox = gtk_vbox_new(0, 2);
167 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
168 gtk_container_add(GTK_CONTAINER(regen_window), vbox);
169 gtk_widget_show (vbox);
170
171 if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) {
172 label = gtk_label_new(_("No key selected to re-generate!"));
173 gtk_box_pack_start(GTK_BOX(vbox), label, 0, 0, 0);
174 gtk_widget_show(label);
175
176 hbox = gtk_hbox_new(FALSE, 2);
177 gtk_box_pack_end(GTK_BOX(vbox), hbox, 0, 0, 0);
178 gtk_widget_show(hbox);
179
180 button = gtk_button_new_with_label(_("OK"));
181 g_signal_connect(G_OBJECT(button), "clicked",
182 GTK_SIGNAL_FUNC(config_cancel_regen), NULL);
183 gtk_box_pack_end(GTK_BOX(hbox), button, 0, 0, 0);
184 gtk_widget_set_size_request(button, 100, -1);
185 gtk_widget_show(button);
186 gtk_widget_show(regen_window);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8)187 return;
188 }
189
190 /* Start 2 x 2 table */
191 table = gtk_table_new(2, 2, FALSE);
192 gtk_box_pack_start(GTK_BOX(vbox), table, 0, 0, 0);
193 gtk_widget_show(table);
194
195 /* First column */
196 label = gtk_label_new(_("Encryption protocol:"));
197 gtk_widget_set_size_request(label, 150, -1);
198 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
199 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
200 0, 0, 0, 0);
201 gtk_widget_show(label);
202
203 label = gtk_label_new(_("Key size:"));
204 gtk_widget_set_size_request(label, 150, -1);
205 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
206 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
207 0, 0, 0, 0);
208 gtk_widget_show(label);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9)209
210 /* Second column: */
211 proto_combo = gtk_combo_new();
212 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(proto_combo)->entry),
213 ((crypt_proto*)crypt_proto_list->data)->name);
214 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(proto_combo)->entry),
215 FALSE);
216 for( iter = crypt_proto_list; iter != NULL; iter = iter->next ) {
217 proto_list = g_list_append(proto_list,
218 ((crypt_proto *)iter->data)->name);
219 }
220 gtk_combo_set_popdown_strings(GTK_COMBO (proto_combo), proto_list);
221 g_list_free(proto_list);
222 gtk_table_attach(GTK_TABLE(table), proto_combo, 1, 2, 0, 1,
223 0, 0, 0, 0);
224
225 gtk_widget_set_size_request(proto_combo, 85, -1);
226 gtk_widget_show(proto_combo);
227
228 key_size_entry = gtk_entry_new();
229 gtk_entry_set_max_length(GTK_ENTRY(key_size_entry), 5);
230 gtk_entry_set_text(GTK_ENTRY(key_size_entry), "1024");
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10)231 gtk_table_attach(GTK_TABLE(table), key_size_entry, 1, 2, 1, 2,
232 0, 0, 0, 0);
233 gtk_widget_set_size_request(key_size_entry, 85, -1);
234 gtk_widget_show(key_size_entry);
235 /* End of 2x2 table */
236
237 regen_err_label = gtk_label_new("");
238 gtk_box_pack_start(GTK_BOX(vbox), regen_err_label, 0, 0, 0);
239 gtk_widget_show(regen_err_label);
240
241 hbox = gtk_hbox_new(FALSE, 2);
242 gtk_box_pack_end(GTK_BOX(vbox), hbox, 0, 0, 0);
243 gtk_widget_show(hbox);
244
245 button = gtk_button_new_with_label(_("Cancel"));
246 g_signal_connect(G_OBJECT(button), "clicked",
247 GTK_SIGNAL_FUNC(config_cancel_regen), NULL);
248 gtk_box_pack_start(GTK_BOX(hbox), button, 0, 0, 0);
249 gtk_widget_set_size_request(button, 100, -1);
250 gtk_widget_show(button);
251
252 button = gtk_button_new_with_label(_("Ok"));
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11)253 g_signal_connect(G_OBJECT(button), "clicked",
254 GTK_SIGNAL_FUNC(config_do_regen), key_list_view);
255 gtk_box_pack_start(GTK_BOX(hbox), button, 0, 0, 0);
256 gtk_widget_set_size_request(button, 100, -1);
257 gtk_widget_show(button);
258
259 gtk_widget_show(regen_window);
260
261 hitbutton = hitbutton; /* unused */
262 }
263
264 /* button handler: */
265 static void delete_local_key(GtkWidget* hitbutton, GtkWidget* key_list_view) {
266 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(key_list_view));
267 GtkListStore *key_list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(key_list_view)));
268 GtkTreeIter list_store_iter;
269
270 gchar *name;
271 PurpleAccount *acct;
272
273 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "delete local key\n");
274
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12)275 if (regen_window != NULL) return;
276
277 if (gtk_tree_selection_get_selected(selection, NULL, &list_store_iter)) {
278
279 gtk_tree_model_get(GTK_TREE_MODEL(key_list_store), &list_store_iter, 0, &name, 4, &acct, -1);
280
281 {
282 GtkWidget * confirm_dialog =
283 gtk_message_dialog_new(0, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
284 "%s : %s", _("Delete Key"), name);
285
286 gint confirm_response = gtk_dialog_run( GTK_DIALOG(confirm_dialog) );
287 gtk_widget_destroy(confirm_dialog);
288
289 if (confirm_response != GTK_RESPONSE_OK) return;
290 }
291
292 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "deleting '%s' : %p\n", name, acct);
293
294 PE_del_key_from_file(Public_key_file, name, acct);
295 PE_del_key_from_file(Private_key_file, name, acct);
296
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13)297 PE_del_key_from_ring(PE_my_pub_ring, name, acct);
298 PE_del_key_from_ring(PE_my_priv_ring, name, acct);
299
300 gtk_list_store_remove(key_list_store, &list_store_iter);
301 }
302
303 hitbutton = hitbutton; /* unused */
304 }
305
306 /* button handler: */
307 static void delete_buddy_key(GtkWidget* hitbutton, GtkWidget* key_list_view) {
308 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(key_list_view));
309 GtkListStore *key_list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(key_list_view)));
310 GtkTreeIter list_store_iter;
311
312 gchar *name;
313 PurpleAccount *acct;
314 gint num;
315
316 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "delete buddy key\n");
317
318 if (regen_window != NULL) return;
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14)319
320 if (gtk_tree_selection_get_selected(selection, NULL, &list_store_iter)) {
321
322 gtk_tree_model_get(GTK_TREE_MODEL(key_list_store), &list_store_iter, 0,
323 &name, 4, &acct, 5, &num, -1);
324
325 {
326 GtkWidget * confirm_dialog =
327 gtk_message_dialog_new(0, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
328 "%s %s", _("Delete Key"), name);
329
330 gint confirm_response = gtk_dialog_run( GTK_DIALOG(confirm_dialog) );
331 gtk_widget_destroy(confirm_dialog);
332
333 if (confirm_response != GTK_RESPONSE_OK) return;
334 }
335
336 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "From file: %d : %s\n", num, name); */
337 PE_del_one_key_from_file(Buddy_key_file, num, name);
338 PE_del_key_from_ring(PE_buddy_ring, name, acct);
339
340 gtk_list_store_remove(key_list_store, &list_store_iter);
341 }
342
343 hitbutton = hitbutton; /* unused */
344 }
345
346 /* button handler: */
347 static void copy_fp_to_clipboard(GtkWidget* hitbutton, GtkWidget* key_list_view) {
348 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(key_list_view));
349 GtkListStore *key_list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(key_list_view)));
350 GtkTreeIter list_store_iter;
351
352 gchar *fptext;
353
354 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "copy to clipboard\n");
355
356 if (regen_window != NULL) return;
357
358 if (gtk_tree_selection_get_selected(selection, NULL, &list_store_iter)) {
359 gtk_tree_model_get(GTK_TREE_MODEL(key_list_store), &list_store_iter, 2, &fptext, -1);
360
361 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "copy :%s:\n", fptext); */
362
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16)363 gtk_clipboard_set_text( gtk_clipboard_get (GDK_SELECTION_PRIMARY), fptext, strlen(fptext) );
364 gtk_clipboard_set_text( gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), fptext, strlen(fptext) );
365 g_free(fptext);
366 }
367
368 hitbutton = hitbutton; /* unused */
369 }
370
371 void PE_populate_key_list_view(key_ring *ring, gboolean local, GtkTreeView* key_list_view) {
372 GtkListStore *store;
373 GtkTreeIter store_iter;
374 GtkCellRenderer *renderer;
375 GtkTreeViewColumn *col;
376 key_ring* iter;
377 GString* key_buf;
378 gint num;
379
380 /* make a list store as a 'model' for the tree view, to store the data in */
381 store = gtk_list_store_new (6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
382 G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT, -1);
383
384 gtk_tree_view_set_model(key_list_view, GTK_TREE_MODEL(store));
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17)385
386 g_object_unref (G_OBJECT(store));
387
388 /* erase any columns that are in the view from previous populations */
389 while (0 != (col = gtk_tree_view_get_column(key_list_view, 0))) {
390 gtk_tree_view_remove_column(key_list_view, col);
391 }
392
393 renderer = gtk_cell_renderer_text_new();
394
395 if (local) {
396 col = gtk_tree_view_column_new_with_attributes(_("Account"), renderer, "text", 0, NULL);
397 } else {
398 col = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", 0, NULL);
399 }
400 gtk_tree_view_append_column(key_list_view, col);
401
402 col = gtk_tree_view_column_new_with_attributes(_("Bits"), renderer, "text", 1, NULL);
403 gtk_tree_view_append_column(key_list_view, col);
404
405 col = gtk_tree_view_column_new_with_attributes(_("Key Fingerprint"), renderer, "text", 2, NULL);
406 gtk_tree_view_append_column(key_list_view, col);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18)407
408 num = 0;
409 for( iter = ring; iter != NULL; iter = iter->next ) {
410 key_ring_data * key_iter = (key_ring_data*)(iter->data);
411
412 gtk_list_store_append(store, &store_iter);
413
414 if (key_iter && key_iter->key && key_iter->key->fingerprint) {
415 key_buf = g_string_new_len(key_iter->key->fingerprint,
416 KEY_FINGERPRINT_LENGTH);
417 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Set List Item: name: '%s', acct: %p, num: %d\n",
418 key_iter->name, key_iter->account, num);
419 } else {
420 key_buf = g_string_new("--error--");
421 purple_debug(PURPLE_DEBUG_WARNING, "pidgin-encryption", "Error Setting List Item %p %p\n",
422 key_iter->key , key_iter->key->fingerprint);
423 }
424
425
426 gtk_list_store_set(store, &store_iter,
427 0, ((key_ring_data *)iter->data)->name,
428 1, ((key_ring_data *)iter->data)->key->length,
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19)429 2, key_buf->str,
430 3, ((key_ring_data *)iter->data)->key->proto->name,
431 4, ((key_ring_data *)iter->data)->account,
432 5, num,
433 -1);
434 g_string_free(key_buf, TRUE);
435 ++num;
436 }
437 }
438
439 GtkWidget* PE_create_key_vbox(GtkWidget** key_list_view) {
440 GtkWidget *keybox = gtk_vbox_new(FALSE, 10);
441 GtkWidget *keywin = gtk_scrolled_window_new(0, 0);
442
443
444 gtk_widget_show(keybox);
445 gtk_box_pack_start(GTK_BOX(keybox), keywin, 0, 0, 0);
446
447 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (keywin),
448 GTK_POLICY_AUTOMATIC,
449 GTK_POLICY_ALWAYS);
450 gtk_widget_set_size_request (keywin, -1, 250);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20)451 gtk_widget_show(keywin);
452
453 *key_list_view = gtk_tree_view_new();
454
455 gtk_container_add(GTK_CONTAINER(keywin), *key_list_view);
456 gtk_widget_show(*key_list_view);
457
458 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(*key_list_view), TRUE);
459
460 return keybox;
461 }
462
463
464 /* Todo: */
465 /* - Make sure we aren't leaking memory on loose widget references */
466
467 /* Called when Purple wants us to show our config dialog */
468
469 GtkWidget* PE_get_config_frame(PurplePlugin *plugin) {
470 GtkWidget *hbox;
471 GtkWidget *keybox;
472 GtkWidget *button;
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21)473 GtkWidget *notebook;
474 GtkWidget *checkbox_vbox;
475
476 config_vbox = gtk_vbox_new(FALSE, 2);
477
478 gtk_container_set_border_width (GTK_CONTAINER (config_vbox), 12);
479
480 gtk_widget_show (config_vbox);
481
482 g_signal_connect(G_OBJECT(config_vbox), "destroy",
483 GTK_SIGNAL_FUNC(config_cancel_regen), NULL);
484
485
486 notebook = gtk_notebook_new();
487 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
488 gtk_box_pack_start(GTK_BOX(config_vbox), notebook, 0, 0, 0);
489 gtk_widget_show(notebook);
490
491
492 /* Notebook page 1: Config */
493
494 checkbox_vbox = gtk_vbox_new(FALSE, 2);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22)495 gtk_container_set_border_width(GTK_CONTAINER(checkbox_vbox), 2);
496 gtk_widget_show(checkbox_vbox);
497 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), checkbox_vbox,
498 gtk_label_new(_("Config")));
499
500 pidgin_prefs_checkbox(_("Accept key automatically if no key on file"),
501 "/plugins/gtk/encrypt/accept_unknown_key", checkbox_vbox);
502
503 pidgin_prefs_checkbox(_("Accept conflicting keys automatically (security risk)"),
504 "/plugins/gtk/encrypt/accept_conflicting_key", checkbox_vbox);
505
506 pidgin_prefs_checkbox(_("Automatically encrypt if sent an encrypted message"),
507 "/plugins/gtk/encrypt/encrypt_response", checkbox_vbox);
508
509 pidgin_prefs_checkbox(_("Broadcast encryption capability"),
510 "/plugins/gtk/encrypt/broadcast_notify", checkbox_vbox);
511
512 pidgin_prefs_checkbox(_("Automatically encrypt if buddy has plugin"),
513 "/plugins/gtk/encrypt/encrypt_if_notified", checkbox_vbox);
514
515 pidgin_prefs_checkbox(_("Show lock icon for each line of chat"),
516 "/plugins/gtk/encrypt/show_inline_icons", checkbox_vbox);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23)517
518 pidgin_prefs_labeled_entry(checkbox_vbox, _("Keyfile location"), "/plugins/gtk/encrypt/key_path_displayed", 0);
519
520 /* sometime box with message and button for when keyfile location is wrong */
521 hbox = gtk_hbox_new(FALSE, 2);
522 Invalid_path_label = gtk_label_new("");
523 gtk_box_pack_start(GTK_BOX(hbox), Invalid_path_label, 0, 0, 0);
524
525 Invalid_path_button = gtk_button_new_with_label(_("Create key files"));
526 g_signal_connect(G_OBJECT(Invalid_path_button), "clicked",
527 GTK_SIGNAL_FUNC(create_key_files_cb), 0);
528 gtk_box_pack_start(GTK_BOX(hbox), Invalid_path_button, 0, 0, 0);
529
530 gtk_box_pack_start(GTK_BOX(checkbox_vbox), hbox, 0, 0, 0);
531 gtk_widget_show(hbox);
532
533 gtk_widget_hide(Invalid_path_button);
534 gtk_widget_set_no_show_all(Invalid_path_button, TRUE);
535
536 /* Notebook page 2: Local keys */
537
538 /* if this assert fails, then the "add_weak_pointer" calls below are gonna cause trouble */
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24)539 assert(Local_keylist_view == NULL);
540 keybox = PE_create_key_vbox(&Local_keylist_view);
541 PE_populate_key_list_view(PE_my_priv_ring, TRUE, GTK_TREE_VIEW(Local_keylist_view));
542
543 hbox = gtk_hbox_new(FALSE, 2);
544 gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
545
546 gtk_box_pack_start(GTK_BOX(keybox), hbox, 0, 0, 0);
547 gtk_widget_show(hbox);
548
549 button = gtk_button_new_with_label(_("Delete Key"));
550 g_signal_connect(G_OBJECT(button), "clicked",
551 GTK_SIGNAL_FUNC(delete_local_key), Local_keylist_view);
552 gtk_box_pack_start(GTK_BOX(hbox), button, 0, 0, 0);
553
554 gtk_widget_show(button);
555
556 button = gtk_button_new_with_label(_("Regenerate Key"));
557 g_signal_connect(G_OBJECT(button), "clicked",
558 GTK_SIGNAL_FUNC(config_regen_key), Local_keylist_view);
559 gtk_box_pack_start(GTK_BOX(hbox), button, 0, 0, 0);
560
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24,T25 const & t25)561 gtk_widget_show(button);
562
563 button = gtk_button_new_with_label(_("Copy Fingerprint to Clipboard"));
564 g_signal_connect(G_OBJECT(button), "clicked",
565 GTK_SIGNAL_FUNC(copy_fp_to_clipboard), Local_keylist_view);
566 gtk_box_pack_end(GTK_BOX(hbox), button, 0, 0, 0);
567
568 gtk_widget_show(button);
569
570
571 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), keybox, gtk_label_new(_("Local Keys")));
572
573
574 /* Notebook page 3: Saved Buddy Keys */
575
576 keybox = PE_create_key_vbox(&Saved_keylist_view);
577 PE_populate_key_list_view(PE_saved_buddy_ring, FALSE, GTK_TREE_VIEW(Saved_keylist_view));
578
579 hbox = gtk_hbox_new(FALSE, 2);
580 gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
581 gtk_box_pack_start(GTK_BOX(keybox), hbox, 0, 0, 0);
582 gtk_widget_show(hbox);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24,T25 const & t25,T26 const & t26)583
584 button = gtk_button_new_with_label(_("Delete Key"));
585 g_signal_connect(G_OBJECT(button), "clicked",
586 GTK_SIGNAL_FUNC(delete_buddy_key), Saved_keylist_view);
587 gtk_box_pack_start(GTK_BOX(hbox), button, 0, 0, 0);
588
589 gtk_widget_show(button);
590
591 button = gtk_button_new_with_label(_("Copy Fingerprint to Clipboard"));
592 g_signal_connect(G_OBJECT(button), "clicked",
593 GTK_SIGNAL_FUNC(copy_fp_to_clipboard), Saved_keylist_view);
594 gtk_box_pack_end(GTK_BOX(hbox), button, 0, 0, 0);
595
596 gtk_widget_show(button);
597
598 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), keybox,
599 gtk_label_new(_("Trusted Buddy Keys")));
600
601
602 /* Notebook page 4: In-Memory Buddy Keys */
603
604 keybox = PE_create_key_vbox(&InMem_keylist_view);
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24,T25 const & t25,T26 const & t26,T27 const & t27)605 PE_populate_key_list_view(PE_buddy_ring, FALSE, GTK_TREE_VIEW(InMem_keylist_view));
606
607 hbox = gtk_hbox_new(FALSE, 2);
608 gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
609 gtk_box_pack_start(GTK_BOX(keybox), hbox, 0, 0, 0);
610 gtk_widget_show(hbox);
611
612 button = gtk_button_new_with_label(_("Delete Key"));
613 g_signal_connect(G_OBJECT(button), "clicked",
614 GTK_SIGNAL_FUNC(delete_buddy_key), InMem_keylist_view);
615 gtk_box_pack_start(GTK_BOX(hbox), button, 0, 0, 0);
616
617 gtk_widget_show(button);
618
619 button = gtk_button_new_with_label(_("Copy Fingerprint to Clipboard"));
620 g_signal_connect(G_OBJECT(button), "clicked",
621 GTK_SIGNAL_FUNC(copy_fp_to_clipboard), InMem_keylist_view);
622 gtk_box_pack_end(GTK_BOX(hbox), button, 0, 0, 0);
623
624 gtk_widget_show(button);
625
626 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), keybox,
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24,T25 const & t25,T26 const & t26,T27 const & t27,T28 const & t28)627 gtk_label_new(_("Recent Buddy Keys")));
628
629
630 /* make it so that when the config_vbox object is finalized, our pointer to it is nulled out */
631 g_object_add_weak_pointer(G_OBJECT(config_vbox), (gpointer*) &config_vbox);
632 g_object_add_weak_pointer(G_OBJECT(Local_keylist_view), (gpointer*) &Local_keylist_view);
633 g_object_add_weak_pointer(G_OBJECT(Saved_keylist_view), (gpointer*) &Saved_keylist_view);
634 g_object_add_weak_pointer(G_OBJECT(InMem_keylist_view), (gpointer*) &InMem_keylist_view);
635
636 g_object_add_weak_pointer(G_OBJECT(Invalid_path_label), (gpointer*) &Invalid_path_label);
637 g_object_add_weak_pointer(G_OBJECT(Invalid_path_button), (gpointer*) &Invalid_path_button);
638
639 return config_vbox;
640 }
641
642 void PE_config_update() {
643 if (!Local_keylist_view) return;
644
645 PE_populate_key_list_view(PE_my_priv_ring, TRUE, GTK_TREE_VIEW(Local_keylist_view));
646 PE_populate_key_list_view(PE_saved_buddy_ring, FALSE, GTK_TREE_VIEW(Saved_keylist_view));
647 PE_populate_key_list_view(PE_buddy_ring, FALSE, GTK_TREE_VIEW(InMem_keylist_view));
648
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24,T25 const & t25,T26 const & t26,T27 const & t27,T28 const & t28,T29 const & t29)649 if (!Invalid_path_label) return;
650 gtk_widget_hide(Invalid_path_label);
651 gtk_widget_hide(Invalid_path_button);
652 }
653
654 void PE_config_show_invalid_keypath() {
655 if (!Invalid_path_label) return;
656
657 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Showing invalid keypath\n");
658 gtk_label_set(GTK_LABEL(Invalid_path_label), _("No key files found at path"));
659 gtk_widget_show(Invalid_path_label);
660 gtk_widget_show(Invalid_path_button);
661 }
662
663 void PE_config_show_nonabsolute_keypath() {
664 if (!Invalid_path_label) return;
665
666 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Showing non-absolute keypath\n");
667 gtk_label_set(GTK_LABEL(Invalid_path_label), _("Absolute path required"));
668 gtk_widget_show(Invalid_path_label);
669 gtk_widget_hide(Invalid_path_button);
670 }
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24,T25 const & t25,T26 const & t26,T27 const & t27,T28 const & t28,T29 const & t29,T30 const & t30)671
672 static void create_key_files_cb( ) {
673 purple_prefs_trigger_callback("/plugins/gtk/encrypt/key_path_displayed");
674 if (PE_check_base_key_path()) {
675 gtk_widget_hide(Invalid_path_label);
676 gtk_widget_hide(Invalid_path_button);
677 } else {
678 gtk_label_set(GTK_LABEL(Invalid_path_label), _("Unable to create key files"));
679 gtk_widget_hide(Invalid_path_button);
680 }
681 }
682
683 void PE_config_unload() {
684 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "PE_config_unload: %p\n", config_vbox);
685 if (config_vbox) {
686 /* We don't want our internal static functions getting called after the plugin */
687 /* has been unloaded, so disconnect the callback that kills the key regen window */
688 /* For good measure, kill the key regen window too */
689
690 g_signal_handlers_disconnect_by_func(GTK_OBJECT(config_vbox),
691 GTK_SIGNAL_FUNC(config_cancel_regen), NULL);
692 config_cancel_regen();
zip(T0 const & t0,T1 const & t1,T2 const & t2,T3 const & t3,T4 const & t4,T5 const & t5,T6 const & t6,T7 const & t7,T8 const & t8,T9 const & t9,T10 const & t10,T11 const & t11,T12 const & t12,T13 const & t13,T14 const & t14,T15 const & t15,T16 const & t16,T17 const & t17,T18 const & t18,T19 const & t19,T20 const & t20,T21 const & t21,T22 const & t22,T23 const & t23,T24 const & t24,T25 const & t25,T26 const & t26,T27 const & t27,T28 const & t28,T29 const & t29,T30 const & t30,T31 const & t31)693 config_vbox = NULL;
694 }
695 }
696