Statistics
| Revision:

root / src / sigstatus.c @ 2303

History | View | Annotate | Download (6.8 kB)

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
44
struct 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
54
static void do_destroy(GpgmegtkSigStatus hd)
55
{
56
        if (!hd->running) {
57
                if (hd->timeout_id_valid) {
58
                        gtk_timeout_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
70
static void okay_cb(GtkWidget *widget, gpointer data)
71
{
72
        GpgmegtkSigStatus hd = data;
73
74
        hd->running = 0;
75
        do_destroy(hd);
76
}
77
78
static 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
88
static 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
100
GpgmegtkSigStatus 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
160
static 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
175
void 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 = gtk_timeout_add(MY_TIMEOUT,
181
                                                         timeout_cb, hd);
182
                        hd->timeout_id_valid = 1;
183
                }
184
                do_destroy(hd);
185
        }
186
}
187
188
void 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
227
const 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 */