Statistics
| Revision:

root / src / sigstatus.c @ 92

History | View | Annotate | Download (6.6 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/gtkwindow.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->mainwindow) {
58
                        gtk_widget_destroy ( hd->mainwindow );
59
                        hd->mainwindow = NULL;
60
                }
61
                if (hd->timeout_id_valid) {
62
                        gtk_timeout_remove(hd->timeout_id);
63
                        hd->timeout_id_valid = 0;
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 gint 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
        }
96
        return FALSE;
97
}
98
99
GpgmegtkSigStatus gpgmegtk_sig_status_create(void)
100
{
101
        GtkWidget *window;
102
        GtkWidget *vbox;
103
        GtkWidget *hbox;
104
        GtkWidget *label;
105
        GtkWidget *okay_btn;
106
        GtkWidget *okay_area;
107
        GpgmegtkSigStatus hd;
108
109
        hd = g_malloc0(sizeof *hd);
110
        hd->running = 1;
111
112
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
113
        hd->mainwindow = window;
114
        gtk_widget_set_size_request(window, 400, -1);
115
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
116
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
117
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
118
        g_signal_connect(G_OBJECT(window), "delete_event",
119
                         G_CALLBACK(delete_event), hd);
120
        g_signal_connect(G_OBJECT(window), "key_press_event",
121
                         G_CALLBACK(key_pressed), hd);
122
123
        vbox = gtk_vbox_new(FALSE, 8);
124
        gtk_container_add(GTK_CONTAINER(window), vbox);
125
        gtk_widget_show(vbox);
126
127
        hbox = gtk_hbox_new(FALSE, 0);
128
        gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 8);
129
        gtk_widget_show(hbox);
130
131
        label = gtk_label_new(_("Checking signature"));
132
        hd->label = label;
133
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
134
        gtk_widget_show(label);
135
136
        gtkut_stock_button_set_create(&okay_area, &okay_btn, GTK_STOCK_OK,
137
                                      NULL, NULL, NULL, NULL);
138
        gtk_box_pack_end(GTK_BOX(vbox), okay_area, FALSE, FALSE, 0);
139
        gtk_widget_grab_default(okay_btn);
140
        g_signal_connect(G_OBJECT(okay_btn), "clicked",
141
                         G_CALLBACK(okay_cb), hd);
142
143
        gtk_widget_show_all(window);
144
145
        while (gtk_events_pending())
146
                gtk_main_iteration();
147
148
        return hd;
149
}
150
151
static gint timeout_cb(gpointer data)
152
{
153
        GpgmegtkSigStatus hd = data;
154
155
        hd->running = 0;
156
        hd->timeout_id_valid = 0;
157
        do_destroy(hd);
158
159
        return FALSE;
160
}
161
162
void gpgmegtk_sig_status_destroy(GpgmegtkSigStatus hd)
163
{
164
        if (hd) {
165
                hd->destroy_pending = 1;
166
                if (hd->running && !hd->timeout_id_valid) {
167
                        hd->timeout_id = gtk_timeout_add(MY_TIMEOUT,
168
                                                         timeout_cb, hd);
169
                        hd->timeout_id_valid = 1;
170
                }
171
                do_destroy(hd);
172
        }
173
}
174
175
void gpgmegtk_sig_status_update(GpgmegtkSigStatus hd, gpgme_ctx_t ctx)
176
{
177
        gpgme_verify_result_t result;
178
        gpgme_signature_t sig;
179
        gchar *text = NULL;
180
181
        if (!hd || !hd->running || !ctx)
182
                return;
183
        result = gpgme_op_verify_result(ctx);
184
        sig = result->signatures;
185
        while (sig) {
186
                gchar *tmp;
187
                const gchar *userid;
188
                gpgme_key_t key = NULL;
189
190
                if (!gpgme_get_key(ctx, sig->fpr, &key, 0)) {
191
                        userid = key->uids->uid;
192
                } else {
193
                        userid = "[?]";
194
                }
195
                tmp = g_strdup_printf(_("%s%s%s from \"%s\""),
196
                                      text ? text : "",
197
                                      text ? "\n" : "",
198
                                gpgmegtk_sig_status_to_string(sig, FALSE),
199
                                      userid);
200
                g_free (text);
201
                text = tmp;
202
                gpgme_key_unref (key);
203
                sig = sig->next;
204
        }
205
        gtk_label_set_text(GTK_LABEL(hd->label), text); 
206
        g_free(text);
207
208
        while (gtk_events_pending())
209
                gtk_main_iteration();
210
}
211
212
const gchar *gpgmegtk_sig_status_to_string(gpgme_signature_t signature,
213
        gboolean use_name)
214
{
215
        const gchar *result = "?";
216
    switch (gpg_err_code(signature->status)) {
217
      case GPG_ERR_NO_DATA:
218
                result = _("No signature found");
219
                break;
220
      case GPG_ERR_NO_ERROR:
221
        switch (signature->validity) {
222
          case GPGME_VALIDITY_ULTIMATE:
223
          case GPGME_VALIDITY_FULL:
224
          case GPGME_VALIDITY_MARGINAL:
225
            result = use_name ? _("Good signature from \"%s\"") :
226
                _("Good signature");
227
            break;
228
          default:
229
            result = use_name ?
230
                _("Valid signature but the key for \"%s\" is not trusted") :
231
                    _("Valid signature (untrusted key)");
232
            break;
233
        }
234
                break;
235
      case GPG_ERR_SIG_EXPIRED:
236
        result = use_name ? _("Signature valid but expired for \"%s\"") :
237
            _("Signature valid but expired");
238
        break;
239
      case GPG_ERR_KEY_EXPIRED:
240
        result = use_name ? _("Signature valid but the signing key for \"%s\" has expired") :
241
            _("Signature valid but the signing key has expired");
242
        break;
243
      case GPG_ERR_CERT_REVOKED:
244
        result = use_name ? _("Signature valid but the signing key for \"%s\" has been revoked") :
245
            _("Signature valid but the signing key has been revoked");
246
        break;
247
      case GPG_ERR_BAD_SIGNATURE:
248
                result = use_name ? _("BAD signature from \"%s\"") :
249
            _("BAD signature");
250
                break;
251
      case GPG_ERR_NO_PUBKEY:
252
                result = _("No public key to verify the signature");
253
                break;
254
        default:
255
        result = _("Error verifying the signature");
256
                break;
257
        }
258
259
        return result;
260
}
261
262
#endif /* USE_GPGME */