Improve some sieve-related translations
[claws.git] / src / plugins / pgpcore / select-keys.c
blob8dd9f8df522cb79d224273fe05dd96f6a35df92e
1 /* select-keys.c - GTK based key selection
2 * Copyright (C) 2001-2022 Werner Koch (dd9jn) and the Claws Mail team
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
22 #ifdef USE_GPGME
23 #include <stdio.h>
24 #include <stdlib.h>
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <gtk/gtk.h>
30 #include "select-keys.h"
31 #include "utils.h"
32 #include "gtkutils.h"
33 #include "inputdialog.h"
34 #include "manage_window.h"
35 #include "alertpanel.h"
37 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
39 enum col_titles {
40 COL_ALGO,
41 COL_KEYID,
42 COL_NAME,
43 COL_ADDRESS,
44 COL_TRUST,
45 COL_PTR,
47 N_COL_TITLES
50 #define COL_ALGO_WIDTH 70
51 #define COL_KEYID_WIDTH 120
52 #define COL_NAME_WIDTH 115
53 #define COL_ADDRESS_WIDTH 140
54 #define COL_TRUST_WIDTH 20
56 struct select_keys_s {
57 int okay;
58 GtkWidget *window;
59 GtkLabel *toplabel;
60 GtkWidget *view;
61 const char *pattern;
62 unsigned int num_keys;
63 gpgme_key_t *kset;
64 gpgme_ctx_t select_ctx;
65 gpgme_protocol_t proto;
66 GtkSortType sort_type;
67 enum col_titles sort_column;
68 SelectionResult result;
72 static void set_row (GtkListStore *store, gpgme_key_t key, gpgme_protocol_t proto);
73 static gpgme_key_t fill_view (struct select_keys_s *sk, const char *pattern,
74 gpgme_protocol_t proto);
75 static void create_dialog (struct select_keys_s *sk);
76 static void open_dialog (struct select_keys_s *sk);
77 static void close_dialog (struct select_keys_s *sk);
78 static gint delete_event_cb (GtkWidget *widget,
79 GdkEventAny *event, gpointer data);
80 static gboolean key_pressed_cb (GtkWidget *widget,
81 GdkEventKey *event, gpointer data);
82 static void select_btn_cb (GtkWidget *widget, gpointer data);
83 static void cancel_btn_cb (GtkWidget *widget, gpointer data);
84 static void dont_encrypt_btn_cb (GtkWidget *widget, gpointer data);
85 static void other_btn_cb (GtkWidget *widget, gpointer data);
87 static gboolean use_untrusted (gpgme_key_t, gpgme_user_id_t uid, gpgme_protocol_t proto);
89 static void
90 update_progress (struct select_keys_s *sk, int running, const char *pattern)
92 static int windmill[] = { '-', '\\', '|', '/' };
93 char *buf;
95 if (!running)
96 buf = g_strdup_printf (_("No exact match for '%s'; please select the key."),
97 pattern);
98 else
99 buf = g_strdup_printf (_("Collecting info for '%s' ... %c"),
100 pattern,
101 windmill[running%DIM(windmill)]);
102 gtk_label_set_text (sk->toplabel, buf);
103 g_free (buf);
108 * gpgmegtk_recipient_selection:
109 * @recp_names: A list of email addresses
111 * Select a list of recipients from a given list of email addresses.
112 * This may pop up a window to present the user a choice, it will also
113 * check that the recipients key are all valid.
115 * Return value: NULL on error or a list of list of recipients.
117 gpgme_key_t *
118 gpgmegtk_recipient_selection (GSList *recp_names, SelectionResult *result,
119 gpgme_protocol_t proto)
121 struct select_keys_s sk;
122 gpgme_key_t key = NULL;
123 memset (&sk, 0, sizeof sk);
125 open_dialog (&sk);
127 do {
128 sk.pattern = recp_names? recp_names->data:NULL;
129 sk.proto = proto;
130 if (sk.view != NULL) {
131 GtkTreeModel *model =
132 gtk_tree_view_get_model(GTK_TREE_VIEW(sk.view));
133 gtk_list_store_clear(GTK_LIST_STORE(model));
135 key = fill_view (&sk, sk.pattern, proto);
136 update_progress (&sk, 0, sk.pattern ? sk.pattern : "NULL");
137 if (!key) {
138 gtk_widget_show_all (sk.window);
139 gtk_main ();
140 } else {
141 gtk_widget_hide (sk.window);
142 sk.kset = g_realloc(sk.kset,
143 sizeof(gpgme_key_t) * (sk.num_keys + 1));
144 gpgme_key_ref(key);
145 sk.kset[sk.num_keys] = key;
146 sk.num_keys++;
147 sk.okay = 1;
148 sk.result = KEY_SELECTION_OK;
149 gpgme_release (sk.select_ctx);
150 sk.select_ctx = NULL;
151 debug_print("used %s\n", key->uids->email);
153 key = NULL;
154 if (recp_names)
155 recp_names = recp_names->next;
156 } while (sk.okay && recp_names);
158 close_dialog (&sk);
160 if (!sk.okay) {
161 g_free(sk.kset);
162 sk.kset = NULL;
163 } else {
164 sk.kset = g_realloc(sk.kset, sizeof(gpgme_key_t) * (sk.num_keys + 1));
165 sk.kset[sk.num_keys] = NULL;
167 if (result)
168 *result = sk.result;
169 return sk.kset;
172 static void
173 set_row (GtkListStore *store, gpgme_key_t key, gpgme_protocol_t proto)
175 const gchar *s;
176 gchar *algo_buf, *name, *address;
177 GtkTreeIter iter;
178 gsize by_read = 0, by_written = 0;
179 gchar *ret_str = NULL;
181 /* first check whether the key is capable of encryption which is not
182 * the case for revoked, expired or sign-only keys */
183 if (!key->can_encrypt || key->revoked || key->expired || key->disabled)
184 return;
186 algo_buf = g_strdup_printf ("%du/%s",
187 key->subkeys->length,
188 gpgme_pubkey_algo_name(key->subkeys->pubkey_algo) );
190 s = key->uids->name;
191 if (!s || !*s)
192 s = key->uids->uid;
193 if (proto == GPGME_PROTOCOL_CMS) {
194 if (strstr(s, ",CN="))
195 s = strstr(s, ",CN=")+4;
196 else if (strstr(s, "CN="))
197 s = strstr(s, "CN=")+3;
200 ret_str = NULL;
201 if (!g_utf8_validate(s, -1, NULL))
202 ret_str = g_locale_to_utf8 (s, strlen(s), &by_read, &by_written, NULL);
203 if (ret_str && by_written) {
204 s = ret_str;
206 name = g_strdup(s);
207 if (ret_str)
208 g_free(ret_str);
210 if (proto == GPGME_PROTOCOL_CMS && (!key->uids->email || !*key->uids->email)) {
211 gpgme_user_id_t uid = key->uids->next;
212 if (uid)
213 s = uid->email;
214 else
215 s = key->uids->email;
216 } else {
217 s = key->uids->email;
220 ret_str = NULL;
221 if (!g_utf8_validate(s, -1, NULL))
222 ret_str = g_locale_to_utf8 (s, strlen(s), &by_read, &by_written, NULL);
223 if (ret_str && by_written) {
224 s = ret_str;
226 address = g_strdup(s);
227 if (ret_str)
228 g_free(ret_str);
230 switch (key->uids->validity)
232 case GPGME_VALIDITY_UNDEFINED:
233 s = _("Undefined");
234 break;
235 case GPGME_VALIDITY_NEVER:
236 s = _("Never");
237 break;
238 case GPGME_VALIDITY_MARGINAL:
239 s = _("Marginal");
240 break;
241 case GPGME_VALIDITY_FULL:
242 s = _("Full");
243 break;
244 case GPGME_VALIDITY_ULTIMATE:
245 s = _("Ultimate");
246 break;
247 case GPGME_VALIDITY_UNKNOWN:
248 default:
249 s = _("Unknown");
250 break;
253 gtk_list_store_append(store, &iter);
254 gtk_list_store_set(store, &iter,
255 COL_ALGO, algo_buf,
256 COL_KEYID, key->subkeys->keyid,
257 COL_NAME, name,
258 COL_ADDRESS, address,
259 COL_TRUST, s,
260 COL_PTR, key,
261 -1);
262 gpgme_key_ref(key);
264 g_free(name);
265 g_free(address);
266 g_free(algo_buf);
269 static gpgme_key_t
270 fill_view (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t proto)
272 GtkWidget *view;
273 GtkTreeModel *model;
274 GtkTreeSelection *sel;
275 GtkTreeIter iter;
276 gpgme_ctx_t ctx;
277 gpgme_error_t err;
278 gpgme_key_t key;
279 int running=0;
280 int num_results = 0;
281 gboolean exact_match = FALSE;
282 gpgme_key_t last_key = NULL;
283 gpgme_user_id_t last_uid = NULL;
285 cm_return_val_if_fail (sk, NULL);
287 view = sk->view;
288 cm_return_val_if_fail (view, NULL);
289 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
291 debug_print ("select_keys:fill_view: pattern '%s' proto %d\n", pattern != NULL ? pattern : "NULL", proto);
293 err = gpgme_new (&ctx);
294 g_assert (!err);
296 gpgme_set_protocol(ctx, proto);
297 sk->select_ctx = ctx;
299 update_progress (sk, ++running, pattern);
300 while (gtk_events_pending ())
301 gtk_main_iteration ();
303 err = gpgme_op_keylist_start (ctx, pattern, 0);
304 if (err) {
305 debug_print ("** gpgme_op_keylist_start(%s) failed: %s\n",
306 pattern != NULL ? pattern : "NULL", gpgme_strerror (err));
307 sk->select_ctx = NULL;
308 gpgme_release(ctx);
309 return NULL;
311 update_progress (sk, ++running, pattern);
312 while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
313 gpgme_user_id_t uid = key->uids;
314 if (!key->can_encrypt || key->revoked || key->expired || key->disabled) {
315 gpgme_key_unref(key);
316 continue;
318 debug_print ("%% %s:%d: insert\n", __FILE__ ,__LINE__ );
319 set_row (GTK_LIST_STORE(model), key, proto );
320 for (; uid; uid = uid->next) {
321 gchar *raw_mail = NULL;
323 if (!uid->email)
324 continue;
325 if (uid->revoked || uid->invalid)
326 continue;
327 raw_mail = g_strdup(uid->email);
328 extract_address(raw_mail);
329 if (pattern != NULL && !strcasecmp(pattern, raw_mail)) {
330 exact_match = TRUE;
331 last_uid = uid;
332 g_free(raw_mail);
333 break;
335 g_free(raw_mail);
338 /* Select the first row */
339 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
340 if (gtk_tree_model_get_iter_first(model, &iter))
341 gtk_tree_selection_select_iter(sel, &iter);
343 num_results++;
344 if (last_key != NULL)
345 gpgme_key_unref(last_key);
346 last_key = key;
347 key = NULL;
348 update_progress (sk, ++running, pattern);
349 while (gtk_events_pending ())
350 gtk_main_iteration ();
353 if (exact_match == TRUE && num_results == 1) {
354 if (last_key->uids->validity < GPGME_VALIDITY_FULL &&
355 !use_untrusted(last_key, last_uid, proto))
356 exact_match = FALSE;
359 debug_print ("%% %s:%d: ready\n", __FILE__ ,__LINE__ );
360 if (gpgme_err_code(err) != GPG_ERR_EOF) {
361 debug_print ("** gpgme_op_keylist_next failed: %s\n",
362 gpgme_strerror (err));
363 gpgme_op_keylist_end(ctx);
365 if (!exact_match || num_results != 1) {
366 sk->select_ctx = NULL;
367 gpgme_release (ctx);
370 if (exact_match && num_results == 1)
371 return last_key;
373 if (last_key != NULL)
374 gpgme_key_unref(last_key);
376 return NULL;
380 static void
381 view_row_activated_cb(GtkTreeView *view,
382 GtkTreePath *path,
383 GtkTreeViewColumn *column,
384 gpointer user_data)
386 select_btn_cb(NULL, user_data);
390 static void
391 create_dialog (struct select_keys_s *sk)
393 GtkWidget *window;
394 GtkWidget *vbox, *vbox2, *hbox;
395 GtkWidget *bbox;
396 GtkWidget *scrolledwin;
397 GtkWidget *view;
398 GtkWidget *label;
399 GtkWidget *select_btn, *cancel_btn, *dont_encrypt_btn, *other_btn;
400 GtkListStore *store;
401 GtkCellRenderer *rdr;
402 GtkTreeViewColumn *col;
403 GtkTreeSelection *sel;
404 gint i = 0;
406 g_assert (!sk->window);
407 window = gtkut_window_new (GTK_WINDOW_TOPLEVEL, "select-keys");
408 gtk_widget_set_size_request (window, 560, 280);
409 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
410 gtk_window_set_title (GTK_WINDOW (window), _("Select Keys"));
411 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
412 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG);
413 g_signal_connect (G_OBJECT (window), "delete_event",
414 G_CALLBACK (delete_event_cb), sk);
415 g_signal_connect (G_OBJECT (window), "key_press_event",
416 G_CALLBACK (key_pressed_cb), sk);
417 MANAGE_WINDOW_SIGNALS_CONNECT (window);
419 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
420 gtk_container_add (GTK_CONTAINER (window), vbox);
422 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
423 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
424 label = gtk_label_new ( "" );
425 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
427 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
428 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
429 gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
431 scrolledwin = gtk_scrolled_window_new (NULL, NULL);
432 gtk_box_pack_start (GTK_BOX (hbox), scrolledwin, TRUE, TRUE, 0);
433 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin),
434 GTK_POLICY_AUTOMATIC,
435 GTK_POLICY_AUTOMATIC);
437 store = gtk_list_store_new(N_COL_TITLES,
438 G_TYPE_STRING,
439 G_TYPE_STRING,
440 G_TYPE_STRING,
441 G_TYPE_STRING,
442 G_TYPE_STRING,
443 G_TYPE_POINTER,
444 -1);
446 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
447 g_object_unref(store);
448 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE);
449 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(view), FALSE);
450 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
451 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
453 rdr = gtk_cell_renderer_text_new();
454 col = gtk_tree_view_column_new_with_attributes(_("Size"), rdr,
455 "markup", COL_ALGO, NULL);
456 gtk_tree_view_column_set_min_width(col, COL_ALGO_WIDTH);
457 gtk_tree_view_column_set_sort_column_id(col, i++);
458 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
460 col = gtk_tree_view_column_new_with_attributes(_("Key ID"), rdr,
461 "markup", COL_KEYID, NULL);
462 gtk_tree_view_column_set_min_width(col, COL_KEYID_WIDTH);
463 gtk_tree_view_column_set_sort_column_id(col, i++);
464 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
466 col = gtk_tree_view_column_new_with_attributes(_("Name"), rdr,
467 "markup", COL_NAME, NULL);
468 gtk_tree_view_column_set_min_width(col, COL_NAME_WIDTH);
469 gtk_tree_view_column_set_sort_column_id(col, i++);
470 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
472 col = gtk_tree_view_column_new_with_attributes(_("Address"), rdr,
473 "markup", COL_ADDRESS, NULL);
474 gtk_tree_view_column_set_min_width(col, COL_ADDRESS_WIDTH);
475 gtk_tree_view_column_set_sort_column_id(col, i++);
476 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
478 col = gtk_tree_view_column_new_with_attributes(_("Trust"), rdr,
479 "markup", COL_TRUST, NULL);
480 gtk_tree_view_column_set_min_width(col, COL_TRUST_WIDTH);
481 gtk_tree_view_column_set_sort_column_id(col, i++);
482 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
484 g_signal_connect(G_OBJECT(view), "row-activated",
485 G_CALLBACK(view_row_activated_cb), sk);
487 gtk_container_add (GTK_CONTAINER (scrolledwin), view);
489 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
490 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
492 /* TRANSLATORS: check that the accelerators in _Select, _Other and
493 * Do_n't encrypt are different than the one in the stock Cancel
494 * button */
495 gtkut_stock_button_set_create (&bbox,
496 &select_btn, NULL, _("_Select"),
497 &other_btn, NULL, _("_Other"),
498 &dont_encrypt_btn, NULL, _("Do_n't encrypt"));
500 cancel_btn = gtk_button_new_with_mnemonic("_Cancel");
501 gtk_widget_set_can_default(cancel_btn, TRUE);
502 gtk_box_pack_start(GTK_BOX(bbox), cancel_btn, TRUE, TRUE, 0);
503 gtk_widget_show(cancel_btn);
504 gtk_box_pack_end (GTK_BOX (hbox), bbox, FALSE, FALSE, 0);
505 gtk_widget_grab_default (select_btn);
507 g_signal_connect (G_OBJECT (select_btn), "clicked",
508 G_CALLBACK (select_btn_cb), sk);
509 g_signal_connect (G_OBJECT(cancel_btn), "clicked",
510 G_CALLBACK (cancel_btn_cb), sk);
511 g_signal_connect (G_OBJECT(dont_encrypt_btn), "clicked",
512 G_CALLBACK (dont_encrypt_btn_cb), sk);
513 g_signal_connect (G_OBJECT (other_btn), "clicked",
514 G_CALLBACK (other_btn_cb), sk);
516 vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
517 gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
519 sk->window = window;
520 sk->toplabel = GTK_LABEL (label);
521 sk->view = view;
525 /* Function called by gtk_tree_model_foreach() upon dialog close,
526 * which unrefs the gpgme_key_t pointer from each model line */
527 static gboolean
528 close_dialog_foreach_func(GtkTreeModel *model,
529 GtkTreePath *path,
530 GtkTreeIter *iter,
531 gpointer user_data)
533 gpgme_key_t key;
535 gtk_tree_model_get(model, iter, COL_PTR, &key, -1);
536 gpgme_key_unref(key);
537 return FALSE;
541 static void
542 open_dialog (struct select_keys_s *sk)
544 if (!sk->window)
545 create_dialog (sk);
546 manage_window_set_transient (GTK_WINDOW (sk->window));
547 sk->okay = 0;
548 sk->sort_column = N_COL_TITLES; /* use an invalid value */
549 sk->sort_type = GTK_SORT_ASCENDING;
553 static void
554 close_dialog (struct select_keys_s *sk)
556 GtkTreeModel *model;
557 cm_return_if_fail (sk);
559 debug_print("pgpcore select-keys dialog closing\n");
560 if (sk->view != NULL) {
561 model = gtk_tree_view_get_model(GTK_TREE_VIEW(sk->view));
562 gtk_tree_model_foreach(model, close_dialog_foreach_func, NULL);
563 gtk_list_store_clear(GTK_LIST_STORE(model));
566 gtk_widget_destroy (sk->window);
567 sk->window = NULL;
571 static gint
572 delete_event_cb (GtkWidget *widget, GdkEventAny *event, gpointer data)
574 struct select_keys_s *sk = data;
576 sk->okay = 0;
577 gtk_main_quit ();
579 return TRUE;
583 static gboolean
584 key_pressed_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
586 struct select_keys_s *sk = data;
588 cm_return_val_if_fail (sk, FALSE);
589 if (event && event->keyval == GDK_KEY_Escape) {
590 sk->okay = 0;
591 gtk_main_quit ();
593 return FALSE;
597 static void
598 select_btn_cb (GtkWidget *widget, gpointer data)
600 struct select_keys_s *sk = data;
601 gboolean use_key;
602 gpgme_key_t key;
604 cm_return_if_fail (sk);
606 key = gtkut_tree_view_get_selected_pointer(
607 GTK_TREE_VIEW(sk->view), COL_PTR,
608 NULL, NULL, NULL);
609 if (key) {
610 gpgme_user_id_t uid;
611 for (uid = key->uids; uid; uid = uid->next) {
612 gchar *raw_mail = NULL;
614 if (!uid->email)
615 continue;
616 raw_mail = g_strdup(uid->email);
617 extract_address(raw_mail);
618 if (sk->pattern && !strcasecmp(sk->pattern, raw_mail)) {
619 g_free(raw_mail);
620 break;
622 g_free(raw_mail);
624 if (!uid)
625 uid = key->uids;
627 if ( uid->validity < GPGME_VALIDITY_FULL ) {
628 use_key = use_untrusted(key, uid, sk->proto);
629 if (!use_key) {
630 debug_print ("** Key untrusted, will not encrypt\n");
631 return;
634 sk->kset = g_realloc(sk->kset,
635 sizeof(gpgme_key_t) * (sk->num_keys + 1));
636 gpgme_key_ref(key);
637 sk->kset[sk->num_keys] = key;
638 sk->num_keys++;
639 sk->okay = 1;
640 sk->result = KEY_SELECTION_OK;
641 gtk_main_quit ();
646 static void
647 cancel_btn_cb (GtkWidget *widget, gpointer data)
649 struct select_keys_s *sk = data;
651 cm_return_if_fail (sk);
652 sk->okay = 0;
653 sk->result = KEY_SELECTION_CANCEL;
654 if (sk->select_ctx)
655 gpgme_cancel (sk->select_ctx);
656 gtk_main_quit ();
659 static void
660 dont_encrypt_btn_cb (GtkWidget *widget, gpointer data)
662 struct select_keys_s *sk = data;
664 cm_return_if_fail (sk);
665 sk->okay = 0;
666 sk->result = KEY_SELECTION_DONT;
667 if (sk->select_ctx)
668 gpgme_cancel (sk->select_ctx);
669 gtk_main_quit ();
672 static void
673 other_btn_cb (GtkWidget *widget, gpointer data)
675 struct select_keys_s *sk = data;
676 char *uid;
678 cm_return_if_fail (sk);
679 uid = input_dialog ( _("Add key"),
680 _("Enter another user or key ID:"),
681 NULL );
682 if (!uid)
683 return;
684 if (fill_view (sk, uid, sk->proto) != NULL) {
685 gpgme_release(sk->select_ctx);
686 sk->select_ctx = NULL;
688 update_progress (sk, 0, sk->pattern);
689 g_free (uid);
693 static gboolean
694 use_untrusted (gpgme_key_t key, gpgme_user_id_t uid, gpgme_protocol_t proto)
696 AlertValue aval;
697 gchar *buf = NULL;
698 gchar *title = NULL;
699 if (proto != GPGME_PROTOCOL_OpenPGP)
700 return TRUE;
702 title = g_strdup_printf(_("Encrypt to %s <%s>"), uid->name, uid->email);
703 buf = g_strdup_printf(_("This encryption key is not fully trusted.\n"
704 "If you choose to encrypt the message with this key, you don't\n"
705 "know for sure that it will go to the person you mean it to.\n\n"
706 "Key details: ID %s, primary identity %s &lt;%s&gt;\n\n"
707 "Do you trust this key enough to use it anyway?"),
708 key->subkeys->keyid, key->uids->name, key->uids->email);
709 aval = alertpanel(title, buf,
710 NULL, _("_No"), NULL, _("_Yes"), NULL, NULL, ALERTFOCUS_FIRST);
711 g_free(buf);
712 g_free(title);
713 if (aval == G_ALERTALTERNATE)
714 return TRUE;
715 else
716 return FALSE;
719 #endif /*USE_GPGME*/