diff options
Diffstat (limited to 'em-format/e-mail-formatter-secure-button.c')
-rw-r--r-- | em-format/e-mail-formatter-secure-button.c | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/em-format/e-mail-formatter-secure-button.c b/em-format/e-mail-formatter-secure-button.c new file mode 100644 index 0000000000..05319ef7fc --- /dev/null +++ b/em-format/e-mail-formatter-secure-button.c @@ -0,0 +1,472 @@ +/* + * evolution-secure-button.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "e-mail-format-extensions.h" + +#include <glib/gi18n-lib.h> + +#include <em-format/e-mail-formatter-extension.h> +#include <em-format/e-mail-formatter.h> +#include <e-util/e-util.h> + +#if defined (HAVE_NSS) && defined (ENABLE_SMIME) +#include "certificate-viewer.h" +#include "e-cert-db.h" +#endif + +#include <camel/camel.h> + +typedef struct _EMailFormatterSecureButton { + GObject parent; +} EMailFormatterSecureButton; + +typedef struct _EMailFormatterSecureButtonClass { + GObjectClass parent_class; +} EMailFormatterSecureButtonClass; + +static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface); +static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface); + +G_DEFINE_TYPE_EXTENDED ( + EMailFormatterSecureButton, + e_mail_formatter_secure_button, + G_TYPE_OBJECT, + 0, + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_EXTENSION, + e_mail_formatter_mail_extension_interface_init) + G_IMPLEMENT_INTERFACE ( + E_TYPE_MAIL_FORMATTER_EXTENSION, + e_mail_formatter_formatter_extension_interface_init)); + +static const gchar *formatter_mime_types[] = { "application/vnd.evolution.widget.secure-button", NULL }; + +static const struct { + const gchar *icon, *shortdesc, *description; +} smime_sign_table[5] = { + { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") }, + { "stock_signature-ok", N_("Valid signature"), N_("This message is signed and is valid meaning that it is very likely that this message is authentic.") }, + { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") }, + { "stock_signature", N_("Valid signature, but cannot verify sender"), N_("This message is signed with a valid signature, but the sender of the message cannot be verified.") }, + { "stock_signature-bad", N_("Signature exists, but need public key"), N_("This message is signed with a signature, but there is no corresponding public key.") }, + +}; + +static const struct { + const gchar *icon, *shortdesc, *description; +} smime_encrypt_table[4] = { + { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") }, + { "stock_lock-ok", N_("Encrypted, weak"), N_("This message is encrypted, but with a weak encryption algorithm. It would be difficult, but not impossible for an outsider to view the content of this message in a practical amount of time.") }, + { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") }, + { "stock_lock-ok", N_("Encrypted, strong"), N_("This message is encrypted, with a strong encryption algorithm. It would be very difficult for an outsider to view the content of this message in a practical amount of time.") }, +}; + +static const GdkRGBA smime_sign_colour[5] = { + { 0 }, { 0.53, 0.73, 0.53, 1 }, { 0.73, 0.53, 0.53, 1 }, { 0.91, 0.82, 0.13, 1 }, { 0 }, +}; + +static gboolean +emfe_secure_button_format (EMailFormatterExtension *extension, + EMailFormatter *formatter, + EMailFormatterContext *context, + EMailPart *part, + CamelStream *stream, + GCancellable *cancellable) +{ + gchar *str; + + if ((context->mode != E_MAIL_FORMATTER_MODE_NORMAL) && + (context->mode != E_MAIL_FORMATTER_MODE_RAW)) + return FALSE; + + str = g_strdup_printf ( + "<object type=\"application/vnd.evolution.widget.secure-button\" " + "height=\"20\" width=\"100%%\" data=\"%s\" id=\"%s\"></object>", + part->id, part->id); + + camel_stream_write_string (stream, str, cancellable, NULL); + + g_free (str); + return TRUE; +} + +#if defined (HAVE_NSS) && defined (ENABLE_SMIME) +static void +viewcert_clicked (GtkWidget *button, + GtkWidget *parent) +{ + CamelCipherCertInfo *info = g_object_get_data((GObject *) button, "e-cert-info"); + ECert *ec = NULL; + + if (info->cert_data) + ec = e_cert_new (CERT_DupCertificate (info->cert_data)); + + if (ec != NULL) { + GtkWidget *w = certificate_viewer_show (ec); + + /* oddly enough certificate_viewer_show doesn't ... */ + gtk_widget_show (w); + g_signal_connect ( + w, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + + if (w && parent) + gtk_window_set_transient_for ( + (GtkWindow *) w, (GtkWindow *) parent); + + g_object_unref (ec); + } else { + g_warning("can't find certificate for %s <%s>", + info->name ? info->name : "", + info->email ? info->email : ""); + } +} +#endif + +static void +info_response (GtkWidget *widget, + guint button, + gpointer user_data) +{ + gtk_widget_destroy (widget); +} + +static void +add_cert_table (GtkWidget *grid, + GQueue *certlist, + gpointer user_data) +{ + GList *head, *link; + GtkTable *table; + gint n = 0; + + table = (GtkTable *) gtk_table_new (certlist->length, 2, FALSE); + + head = g_queue_peek_head_link (certlist); + + for (link = head; link != NULL; link = g_list_next (link)) { + CamelCipherCertInfo *info = link->data; + gchar *la = NULL; + const gchar *l = NULL; + + if (info->name) { + if (info->email && strcmp (info->name, info->email) != 0) + l = la = g_strdup_printf("%s <%s>", info->name, info->email); + else + l = info->name; + } else { + if (info->email) + l = info->email; + } + + if (l) { + GtkWidget *w; +#if defined (HAVE_NSS) && defined (ENABLE_SMIME) + ECert *ec = NULL; +#endif + w = gtk_label_new (l); + gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5); + g_free (la); + gtk_table_attach (table, w, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 3, 3); +#if defined (HAVE_NSS) && defined (ENABLE_SMIME) + w = gtk_button_new_with_mnemonic(_("_View Certificate")); + gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3); + g_object_set_data((GObject *)w, "e-cert-info", info); + g_signal_connect ( + w, "clicked", + G_CALLBACK (viewcert_clicked), grid); + + if (info->cert_data) + ec = e_cert_new (CERT_DupCertificate (info->cert_data)); + + if (ec == NULL) + gtk_widget_set_sensitive (w, FALSE); + else + g_object_unref (ec); +#else + w = gtk_label_new (_("This certificate is not viewable")); + gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3); +#endif + n++; + } + } + + gtk_container_add (GTK_CONTAINER (grid), GTK_WIDGET (table)); +} + +static void +format_cert_infos (GQueue *cert_infos, + GString *output_buffer) +{ + GQueue valid = G_QUEUE_INIT; + GList *head, *link; + + head = g_queue_peek_head_link (cert_infos); + + /* Make sure we have a valid CamelCipherCertInfo before + * appending anything to the output buffer, so we don't + * end up with "()". */ + for (link = head; link != NULL; link = g_list_next (link)) { + CamelCipherCertInfo *cinfo = link->data; + + if ((cinfo->name != NULL && *cinfo->name != '\0') || + (cinfo->email != NULL && *cinfo->email != '\0')) { + g_queue_push_tail (&valid, cinfo); + } + } + + if (g_queue_is_empty (&valid)) + return; + + g_string_append (output_buffer, " ("); + + while (!g_queue_is_empty (&valid)) { + CamelCipherCertInfo *cinfo; + + cinfo = g_queue_pop_head (&valid); + + if (cinfo->name != NULL && *cinfo->name != '\0') { + g_string_append (output_buffer, cinfo->name); + + if (cinfo->email != NULL && *cinfo->email != '\0') { + g_string_append (output_buffer, " <"); + g_string_append (output_buffer, cinfo->email); + g_string_append (output_buffer, ">"); + } + + } else if (cinfo->email != NULL && *cinfo->email != '\0') { + g_string_append (output_buffer, cinfo->email); + } + + if (!g_queue_is_empty (&valid)) + g_string_append (output_buffer, ", "); + } + + g_string_append_c (output_buffer, ')'); +} + +static void +secure_button_clicked_cb (GtkWidget *widget, + EMailPart *part) +{ + GtkBuilder *builder; + GtkWidget *grid, *w; + GtkWidget *dialog; + + builder = gtk_builder_new (); + e_load_ui_builder_definition (builder, "mail-dialogs.ui"); + + dialog = e_builder_get_widget(builder, "message_security_dialog"); + + grid = e_builder_get_widget(builder, "signature_grid"); + w = gtk_label_new (_(smime_sign_table[part->validity->sign.status].description)); + gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5); + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_container_add (GTK_CONTAINER (grid), w); + if (part->validity->sign.description) { + GtkTextBuffer *buffer; + + buffer = gtk_text_buffer_new (NULL); + gtk_text_buffer_set_text ( + buffer, part->validity->sign.description, + strlen (part->validity->sign.description)); + w = g_object_new (gtk_scrolled_window_get_type (), + "hscrollbar_policy", GTK_POLICY_AUTOMATIC, + "vscrollbar_policy", GTK_POLICY_AUTOMATIC, + "shadow_type", GTK_SHADOW_IN, + "expand", TRUE, + "child", g_object_new(gtk_text_view_get_type(), + "buffer", buffer, + "cursor_visible", FALSE, + "editable", FALSE, + "width_request", 500, + "height_request", 160, + NULL), + NULL); + g_object_unref (buffer); + + gtk_container_add (GTK_CONTAINER (grid), w); + } + + if (!g_queue_is_empty (&part->validity->sign.signers)) + add_cert_table ( + grid, &part->validity->sign.signers, NULL); + + gtk_widget_show_all (grid); + + grid = e_builder_get_widget(builder, "encryption_grid"); + w = gtk_label_new (_(smime_encrypt_table[part->validity->encrypt.status].description)); + gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5); + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_container_add (GTK_CONTAINER (grid), w); + if (part->validity->encrypt.description) { + GtkTextBuffer *buffer; + + buffer = gtk_text_buffer_new (NULL); + gtk_text_buffer_set_text ( + buffer, part->validity->encrypt.description, + strlen (part->validity->encrypt.description)); + w = g_object_new (gtk_scrolled_window_get_type (), + "hscrollbar_policy", GTK_POLICY_AUTOMATIC, + "vscrollbar_policy", GTK_POLICY_AUTOMATIC, + "shadow_type", GTK_SHADOW_IN, + "expand", TRUE, + "child", g_object_new(gtk_text_view_get_type(), + "buffer", buffer, + "cursor_visible", FALSE, + "editable", FALSE, + "width_request", 500, + "height_request", 160, + NULL), + NULL); + g_object_unref (buffer); + + gtk_container_add (GTK_CONTAINER (grid), w); + } + + if (!g_queue_is_empty (&part->validity->encrypt.encrypters)) + add_cert_table (grid, &part->validity->encrypt.encrypters, NULL); + + gtk_widget_show_all (grid); + + g_object_unref (builder); + + g_signal_connect ( + dialog, "response", + G_CALLBACK (info_response), NULL); + + gtk_widget_show (dialog); +} + +static GtkWidget * +emfe_secure_button_get_widget (EMailFormatterExtension *extension, + EMailPartList *context, + EMailPart *part, + GHashTable *params) +{ + GtkWidget *box, *button, *layout, *widget; + const gchar *icon_name; + gchar *description; + GString *buffer; + buffer = g_string_new (""); + + if (part->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) { + const gchar *desc; + gint status; + + status = part->validity->sign.status; + desc = smime_sign_table[status].shortdesc; + + g_string_append (buffer, gettext (desc)); + + format_cert_infos (&part->validity->sign.signers, buffer); + } + + if (part->validity->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) { + const gchar *desc; + gint status; + + if (part->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) + g_string_append (buffer, "\n"); + + status = part->validity->encrypt.status; + desc = smime_encrypt_table[status].shortdesc; + g_string_append (buffer, gettext (desc)); + } + + description = g_string_free (buffer, FALSE); + + /* FIXME: need to have it based on encryption and signing too */ + if (part->validity->sign.status != 0) + icon_name = smime_sign_table[part->validity->sign.status].icon; + else + icon_name = smime_encrypt_table[part->validity->encrypt.status].icon; + + box = gtk_event_box_new (); + if (part->validity->sign.status != 0) + gtk_widget_override_background_color (box, GTK_STATE_FLAG_NORMAL, + &smime_sign_colour[part->validity->sign.status]); + + layout = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_container_add (GTK_CONTAINER (box), layout); + + button = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (layout), button, FALSE, FALSE, 0); + g_signal_connect (button, "clicked", + G_CALLBACK (secure_button_clicked_cb), part); + + widget = gtk_image_new_from_icon_name ( + icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_button_set_image (GTK_BUTTON (button), widget); + + widget = gtk_label_new (description); + gtk_box_pack_start (GTK_BOX (layout), widget, FALSE, FALSE, 0); + + gtk_widget_show_all (box); + + g_free (description); + return box; +} + +static const gchar * +emfe_secure_button_get_display_name (EMailFormatterExtension *extension) +{ + return NULL; +} + +static const gchar * +emfe_secure_button_get_description (EMailFormatterExtension *extension) +{ + return NULL; +} + +static const gchar ** +emfe_secure_button_mime_types (EMailExtension *extension) +{ + return formatter_mime_types; +} + +static void +e_mail_formatter_secure_button_class_init (EMailFormatterSecureButtonClass *klass) +{ + e_mail_formatter_secure_button_parent_class = g_type_class_peek_parent (klass); +} + +static void +e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface) +{ + iface->format = emfe_secure_button_format; + iface->get_widget = emfe_secure_button_get_widget; + iface->get_display_name = emfe_secure_button_get_display_name; + iface->get_description = emfe_secure_button_get_description; +} + +static void +e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface) +{ + iface->mime_types = emfe_secure_button_mime_types; +} + +static void +e_mail_formatter_secure_button_init (EMailFormatterSecureButton *extension) +{ + +} |