diff options
| author | Simeon Simeonov | 2018-02-26 11:23:00 +0100 |
|---|---|---|
| committer | Simeon Simeonov | 2018-02-26 11:23:00 +0100 |
| commit | 0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch) | |
| tree | af916a30553c78ce9d4f2d8658656a175c5b6921 /src/sigstatus.c | |
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'src/sigstatus.c')
| -rw-r--r-- | src/sigstatus.c | 280 |
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 | |||
| 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 | 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 | |||
| 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 = g_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 */ | ||
