summaryrefslogtreecommitdiff
path: root/src/sigstatus.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sigstatus.c')
-rw-r--r--src/sigstatus.c280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/sigstatus.c b/src/sigstatus.c
new file mode 100644
index 0000000..4f777e7
--- /dev/null
+++ b/src/sigstatus.c
@@ -0,0 +1,280 @@
1/* sigstatus.h - GTK+ based signature status display
2 * Copyright (C) 2001 Werner Koch (dd9jn)
3 *
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 2 of the License, or
7 * (at your option) any later version.
8 *
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.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#if USE_GPGME
24
25#include <glib.h>
26#include <glib/gi18n.h>
27#include <gtk/gtkdialog.h>
28#include <gtk/gtkvbox.h>
29#include <gtk/gtkhbox.h>
30#include <gtk/gtklabel.h>
31#include <gtk/gtkbutton.h>
32#include <gtk/gtkstock.h>
33#include <gdk/gdkkeysyms.h>
34#include <gpgme.h>
35
36#include "gtkutils.h"
37#include "utils.h"
38#include "sigstatus.h"
39
40/* remove the window after 30 seconds to avoid cluttering the deskop
41 * with too many of them */
42#define MY_TIMEOUT (30*1000)
43
44struct gpgmegtk_sig_status_s {
45 GtkWidget *mainwindow;
46 GtkWidget *label;
47 gint running;
48 gint destroy_pending;
49 guint timeout_id;
50 gint timeout_id_valid;
51};
52
53
54static void do_destroy(GpgmegtkSigStatus hd)
55{
56 if (!hd->running) {
57 if (hd->timeout_id_valid) {
58 g_source_remove(hd->timeout_id);
59 hd->timeout_id_valid = 0;
60 }
61 if (hd->mainwindow) {
62 gtk_widget_destroy ( hd->mainwindow );
63 hd->mainwindow = NULL;
64 }
65 if (hd->destroy_pending)
66 g_free(hd);
67 }
68}
69
70static void okay_cb(GtkWidget *widget, gpointer data)
71{
72 GpgmegtkSigStatus hd = data;
73
74 hd->running = 0;
75 do_destroy(hd);
76}
77
78static gboolean delete_event(GtkWidget *widget, GdkEventAny *event, gpointer data)
79{
80 GpgmegtkSigStatus hd = data;
81
82 hd->running = 0;
83 do_destroy(hd);
84
85 return TRUE;
86}
87
88static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
89{
90 GpgmegtkSigStatus hd = data;
91
92 if (event && event->keyval == GDK_Escape) {
93 hd->running = 0;
94 do_destroy(hd);
95 return TRUE;
96 }
97 return FALSE;
98}
99
100GpgmegtkSigStatus gpgmegtk_sig_status_create(void)
101{
102 GtkWidget *window;
103 GtkWidget *vbox;
104 GtkWidget *hbox;
105 GtkWidget *label;
106 GtkWidget *okay_btn;
107 GtkWidget *okay_area;
108 GpgmegtkSigStatus hd;
109
110 hd = g_malloc0(sizeof *hd);
111 hd->running = 1;
112
113 window = gtk_dialog_new();
114 hd->mainwindow = window;
115 gtk_widget_set_size_request(window, 400, -1);
116 gtk_window_set_title(GTK_WINDOW(window), _("Signature check result"));
117 gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
118 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
119 gtk_dialog_set_has_separator(GTK_DIALOG(window), FALSE);
120 g_signal_connect(G_OBJECT(window), "delete_event",
121 G_CALLBACK(delete_event), hd);
122 g_signal_connect(G_OBJECT(window), "key_press_event",
123 G_CALLBACK(key_pressed), hd);
124
125 vbox = gtk_vbox_new(FALSE, 8);
126 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
127 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),
128 vbox, TRUE, TRUE, 0);
129 gtk_widget_show(vbox);
130
131 hbox = gtk_hbox_new(FALSE, 0);
132 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
133 gtk_widget_show(hbox);
134
135 label = gtk_label_new(_("Checking signature"));
136 hd->label = label;
137 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
138 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
139 gtk_label_set_selectable(GTK_LABEL(label), TRUE);
140 gtk_widget_show(label);
141
142 gtkut_stock_button_set_create(&okay_area, &okay_btn, GTK_STOCK_OK,
143 NULL, NULL, NULL, NULL);
144 gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area),
145 okay_area, FALSE, FALSE, 0);
146 gtk_container_set_border_width(GTK_CONTAINER(okay_area), 5);
147 gtk_widget_grab_default(okay_btn);
148 gtk_widget_grab_focus(okay_btn);
149 g_signal_connect(G_OBJECT(okay_btn), "clicked",
150 G_CALLBACK(okay_cb), hd);
151
152 gtk_widget_show_all(window);
153
154 while (gtk_events_pending())
155 gtk_main_iteration();
156
157 return hd;
158}
159
160static gint timeout_cb(gpointer data)
161{
162 GpgmegtkSigStatus hd = data;
163
164 gdk_threads_enter();
165
166 hd->running = 0;
167 hd->timeout_id_valid = 0;
168 do_destroy(hd);
169
170 gdk_threads_leave();
171
172 return FALSE;
173}
174
175void gpgmegtk_sig_status_destroy(GpgmegtkSigStatus hd)
176{
177 if (hd) {
178 hd->destroy_pending = 1;
179 if (hd->running && !hd->timeout_id_valid) {
180 hd->timeout_id = g_timeout_add(MY_TIMEOUT,
181 timeout_cb, hd);
182 hd->timeout_id_valid = 1;
183 }
184 do_destroy(hd);
185 }
186}
187
188void gpgmegtk_sig_status_update(GpgmegtkSigStatus hd, gpgme_ctx_t ctx)
189{
190 gpgme_verify_result_t result;
191 gpgme_signature_t sig;
192 gchar *text = NULL;
193
194 if (!hd || !hd->running || !ctx)
195 return;
196 result = gpgme_op_verify_result(ctx);
197 if (!result)
198 return;
199
200 sig = result->signatures;
201 while (sig) {
202 gchar *tmp;
203 const gchar *userid;
204 gpgme_key_t key = NULL;
205
206 if (!gpgme_get_key(ctx, sig->fpr, &key, 0)) {
207 userid = key->uids->uid;
208 } else {
209 userid = "[?]";
210 }
211 tmp = g_strdup_printf
212 (_("%s%s%s from \"%s\""),
213 text ? text : "", text ? "\n" : "",
214 gpgmegtk_sig_status_to_string(sig, FALSE), userid);
215 g_free (text);
216 text = tmp;
217 gpgme_key_unref (key);
218 sig = sig->next;
219 }
220 gtk_label_set_text(GTK_LABEL(hd->label), text);
221 g_free(text);
222
223 while (gtk_events_pending())
224 gtk_main_iteration();
225}
226
227const gchar *gpgmegtk_sig_status_to_string(gpgme_signature_t signature,
228 gboolean use_name)
229{
230 const gchar *result = "?";
231
232 g_return_val_if_fail(signature != NULL, result);
233
234 switch (gpg_err_code(signature->status)) {
235 case GPG_ERR_NO_DATA:
236 result = _("No signature found");
237 break;
238 case GPG_ERR_NO_ERROR:
239 switch (signature->validity) {
240 case GPGME_VALIDITY_ULTIMATE:
241 case GPGME_VALIDITY_FULL:
242 case GPGME_VALIDITY_MARGINAL:
243 result = use_name ? _("Good signature from \"%s\"") :
244 _("Good signature");
245 break;
246 default:
247 result = use_name ?
248 _("Valid signature but the key for \"%s\" is not trusted") :
249 _("Valid signature (untrusted key)");
250 break;
251 }
252 break;
253 case GPG_ERR_SIG_EXPIRED:
254 result = use_name ? _("Signature valid but expired for \"%s\"") :
255 _("Signature valid but expired");
256 break;
257 case GPG_ERR_KEY_EXPIRED:
258 result = use_name ? _("Signature valid but the signing key for \"%s\" has expired") :
259 _("Signature valid but the signing key has expired");
260 break;
261 case GPG_ERR_CERT_REVOKED:
262 result = use_name ? _("Signature valid but the signing key for \"%s\" has been revoked") :
263 _("Signature valid but the signing key has been revoked");
264 break;
265 case GPG_ERR_BAD_SIGNATURE:
266 result = use_name ? _("BAD signature from \"%s\"") :
267 _("BAD signature");
268 break;
269 case GPG_ERR_NO_PUBKEY:
270 result = _("No public key to verify the signature");
271 break;
272 default:
273 result = _("Error verifying the signature");
274 break;
275 }
276
277 return result;
278}
279
280#endif /* USE_GPGME */