No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-mail-formatter-secure-button.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-mail-formatter-secure-button.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * evolution-secure-button.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
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 GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 #include "e-mail-format-extensions.h"
23
24 #include <glib/gi18n-lib.h>
25
26 #include <em-format/e-mail-formatter-extension.h>
27 #include <em-format/e-mail-formatter.h>
28 #include <e-util/e-util.h>
29
30 #if defined (HAVE_NSS) && defined (ENABLE_SMIME)
31 #include "certificate-viewer.h"
32 #include "e-cert-db.h"
33 #endif
34
35 #include <camel/camel.h>
36
37 typedef struct _EMailFormatterSecureButton {
38 GObject parent;
39 } EMailFormatterSecureButton;
40
41 typedef struct _EMailFormatterSecureButtonClass {
42 GObjectClass parent_class;
43 } EMailFormatterSecureButtonClass;
44
45 static void e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface);
46 static void e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface);
47
48 G_DEFINE_TYPE_EXTENDED (
49 EMailFormatterSecureButton,
50 e_mail_formatter_secure_button,
51 G_TYPE_OBJECT,
52 0,
53 G_IMPLEMENT_INTERFACE (
54 E_TYPE_MAIL_EXTENSION,
55 e_mail_formatter_mail_extension_interface_init)
56 G_IMPLEMENT_INTERFACE (
57 E_TYPE_MAIL_FORMATTER_EXTENSION,
58 e_mail_formatter_formatter_extension_interface_init));
59
60 static const gchar *formatter_mime_types[] = { "application/vnd.evolution.widget.secure-button", NULL };
61
62 static const struct {
63 const gchar *icon, *shortdesc, *description;
64 } smime_sign_table[5] = {
65 { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") },
66 { "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.") },
67 { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") },
68 { "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.") },
69 { "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.") },
70
71 };
72
73 static const struct {
74 const gchar *icon, *shortdesc, *description;
75 } smime_encrypt_table[4] = {
76 { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") },
77 { "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.") },
78 { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") },
79 { "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.") },
80 };
81
82 static const GdkRGBA smime_sign_colour[5] = {
83 { 0 }, { 0.53, 0.73, 0.53, 1 }, { 0.73, 0.53, 0.53, 1 }, { 0.91, 0.82, 0.13, 1 }, { 0 },
84 };
85
86 static gboolean
87 emfe_secure_button_format (EMailFormatterExtension *extension,
88 EMailFormatter *formatter,
89 EMailFormatterContext *context,
90 EMailPart *part,
91 CamelStream *stream,
92 GCancellable *cancellable)
93 {
94 gchar *str;
95
96 if ((context->mode != E_MAIL_FORMATTER_MODE_NORMAL) &&
97 (context->mode != E_MAIL_FORMATTER_MODE_RAW) &&
98 (context->mode != E_MAIL_FORMATTER_MODE_ALL_HEADERS))
99 return FALSE;
100
101 str = g_strdup_printf (
102 "<object type=\"application/vnd.evolution.widget.secure-button\" "
103 "height=\"20\" width=\"100%%\" data=\"%s\" id=\"%s\"></object>",
104 part->id, part->id);
105
106 camel_stream_write_string (stream, str, cancellable, NULL);
107
108 g_free (str);
109 return TRUE;
110 }
111
112 #if defined (HAVE_NSS) && defined (ENABLE_SMIME)
113 static void
114 viewcert_clicked (GtkWidget *button,
115 GtkWidget *parent)
116 {
117 CamelCipherCertInfo *info = g_object_get_data ((GObject *) button, "e-cert-info");
118 ECert *ec = NULL;
119
120 if (info->cert_data)
121 ec = e_cert_new (CERT_DupCertificate (info->cert_data));
122
123 if (ec != NULL) {
124 GtkWidget *w = certificate_viewer_show (ec);
125
126 /* oddly enough certificate_viewer_show doesn't ... */
127 gtk_widget_show (w);
128 g_signal_connect (
129 w, "response",
130 G_CALLBACK (gtk_widget_destroy), NULL);
131
132 if (w && parent)
133 gtk_window_set_transient_for (
134 (GtkWindow *) w, (GtkWindow *) parent);
135
136 g_object_unref (ec);
137 } else {
138 g_warning (
139 "can't find certificate for %s <%s>",
140 info->name ? info->name : "",
141 info->email ? info->email : "");
142 }
143 }
144 #endif
145
146 static void
147 info_response (GtkWidget *widget,
148 guint button,
149 gpointer user_data)
150 {
151 gtk_widget_destroy (widget);
152 }
153
154 static void
155 add_cert_table (GtkWidget *grid,
156 GQueue *certlist,
157 gpointer user_data)
158 {
159 GList *head, *link;
160 GtkTable *table;
161 gint n = 0;
162
163 table = (GtkTable *) gtk_table_new (certlist->length, 2, FALSE);
164
165 head = g_queue_peek_head_link (certlist);
166
167 for (link = head; link != NULL; link = g_list_next (link)) {
168 CamelCipherCertInfo *info = link->data;
169 gchar *la = NULL;
170 const gchar *l = NULL;
171
172 if (info->name) {
173 if (info->email && strcmp (info->name, info->email) != 0)
174 l = la = g_strdup_printf ("%s <%s>", info->name, info->email);
175 else
176 l = info->name;
177 } else {
178 if (info->email)
179 l = info->email;
180 }
181
182 if (l) {
183 GtkWidget *w;
184 #if defined (HAVE_NSS) && defined (ENABLE_SMIME)
185 ECert *ec = NULL;
186 #endif
187 w = gtk_label_new (l);
188 gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
189 g_free (la);
190 gtk_table_attach (table, w, 0, 1, n, n + 1, GTK_FILL, GTK_FILL, 3, 3);
191 #if defined (HAVE_NSS) && defined (ENABLE_SMIME)
192 w = gtk_button_new_with_mnemonic (_("_View Certificate"));
193 gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3);
194 g_object_set_data ((GObject *) w, "e-cert-info", info);
195 g_signal_connect (
196 w, "clicked",
197 G_CALLBACK (viewcert_clicked), grid);
198
199 if (info->cert_data)
200 ec = e_cert_new (CERT_DupCertificate (info->cert_data));
201
202 if (ec == NULL)
203 gtk_widget_set_sensitive (w, FALSE);
204 else
205 g_object_unref (ec);
206 #else
207 w = gtk_label_new (_("This certificate is not viewable"));
208 gtk_table_attach (table, w, 1, 2, n, n + 1, 0, 0, 3, 3);
209 #endif
210 n++;
211 }
212 }
213
214 gtk_container_add (GTK_CONTAINER (grid), GTK_WIDGET (table));
215 }
216
217 static void
218 format_cert_infos (GQueue *cert_infos,
219 GString *output_buffer)
220 {
221 GQueue valid = G_QUEUE_INIT;
222 GList *head, *link;
223
224 head = g_queue_peek_head_link (cert_infos);
225
226 /* Make sure we have a valid CamelCipherCertInfo before
227 * appending anything to the output buffer, so we don't
228 * end up with "()". */
229 for (link = head; link != NULL; link = g_list_next (link)) {
230 CamelCipherCertInfo *cinfo = link->data;
231
232 if ((cinfo->name != NULL && *cinfo->name != '\0') ||
233 (cinfo->email != NULL && *cinfo->email != '\0')) {
234 g_queue_push_tail (&valid, cinfo);
235 }
236 }
237
238 if (g_queue_is_empty (&valid))
239 return;
240
241 g_string_append (output_buffer, " (");
242
243 while (!g_queue_is_empty (&valid)) {
244 CamelCipherCertInfo *cinfo;
245
246 cinfo = g_queue_pop_head (&valid);
247
248 if (cinfo->name != NULL && *cinfo->name != '\0') {
249 g_string_append (output_buffer, cinfo->name);
250
251 if (cinfo->email != NULL && *cinfo->email != '\0') {
252 g_string_append (output_buffer, " <");
253 g_string_append (output_buffer, cinfo->email);
254 g_string_append (output_buffer, ">");
255 }
256
257 } else if (cinfo->email != NULL && *cinfo->email != '\0') {
258 g_string_append (output_buffer, cinfo->email);
259 }
260
261 if (!g_queue_is_empty (&valid))
262 g_string_append (output_buffer, ", ");
263 }
264
265 g_string_append_c (output_buffer, ')');
266 }
267
268 static void
269 secure_button_clicked_cb (GtkWidget *widget,
270 EMailPart *part)
271 {
272 GtkBuilder *builder;
273 GtkWidget *grid, *w;
274 GtkWidget *dialog;
275
276 builder = gtk_builder_new ();
277 e_load_ui_builder_definition (builder, "mail-dialogs.ui");
278
279 dialog = e_builder_get_widget (builder, "message_security_dialog");
280
281 grid = e_builder_get_widget (builder, "signature_grid");
282 w = gtk_label_new (_(smime_sign_table[part->validity->sign.status].description));
283 gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
284 gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
285 gtk_container_add (GTK_CONTAINER (grid), w);
286 if (part->validity->sign.description) {
287 GtkTextBuffer *buffer;
288
289 buffer = gtk_text_buffer_new (NULL);
290 gtk_text_buffer_set_text (
291 buffer, part->validity->sign.description,
292 strlen (part->validity->sign.description));
293 w = g_object_new (
294 gtk_scrolled_window_get_type (),
295 "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
296 "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
297 "shadow_type", GTK_SHADOW_IN,
298 "expand", TRUE,
299 "child", g_object_new (gtk_text_view_get_type (),
300 "buffer", buffer,
301 "cursor_visible", FALSE,
302 "editable", FALSE,
303 "width_request", 500,
304 "height_request", 160,
305 NULL),
306 NULL);
307 g_object_unref (buffer);
308
309 gtk_container_add (GTK_CONTAINER (grid), w);
310 }
311
312 if (!g_queue_is_empty (&part->validity->sign.signers))
313 add_cert_table (
314 grid, &part->validity->sign.signers, NULL);
315
316 gtk_widget_show_all (grid);
317
318 grid = e_builder_get_widget (builder, "encryption_grid");
319 w = gtk_label_new (_(smime_encrypt_table[part->validity->encrypt.status].description));
320 gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
321 gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
322 gtk_container_add (GTK_CONTAINER (grid), w);
323 if (part->validity->encrypt.description) {
324 GtkTextBuffer *buffer;
325
326 buffer = gtk_text_buffer_new (NULL);
327 gtk_text_buffer_set_text (
328 buffer, part->validity->encrypt.description,
329 strlen (part->validity->encrypt.description));
330 w = g_object_new (
331 gtk_scrolled_window_get_type (),
332 "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
333 "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
334 "shadow_type", GTK_SHADOW_IN,
335 "expand", TRUE,
336 "child", g_object_new (gtk_text_view_get_type (),
337 "buffer", buffer,
338 "cursor_visible", FALSE,
339 "editable", FALSE,
340 "width_request", 500,
341 "height_request", 160,
342 NULL),
343 NULL);
344 g_object_unref (buffer);
345
346 gtk_container_add (GTK_CONTAINER (grid), w);
347 }
348
349 if (!g_queue_is_empty (&part->validity->encrypt.encrypters))
350 add_cert_table (grid, &part->validity->encrypt.encrypters, NULL);
351
352 gtk_widget_show_all (grid);
353
354 g_object_unref (builder);
355
356 g_signal_connect (
357 dialog, "response",
358 G_CALLBACK (info_response), NULL);
359
360 gtk_widget_show (dialog);
361 }
362
363 static GtkWidget *
364 emfe_secure_button_get_widget (EMailFormatterExtension *extension,
365 EMailPartList *context,
366 EMailPart *part,
367 GHashTable *params)
368 {
369 GtkWidget *box, *button, *layout, *widget;
370 const gchar *icon_name;
371 gchar *description;
372 GString *buffer;
373 buffer = g_string_new ("");
374
375 if (part->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
376 const gchar *desc;
377 gint status;
378
379 status = part->validity->sign.status;
380 desc = smime_sign_table[status].shortdesc;
381
382 g_string_append (buffer, gettext (desc));
383
384 format_cert_infos (&part->validity->sign.signers, buffer);
385 }
386
387 if (part->validity->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
388 const gchar *desc;
389 gint status;
390
391 if (part->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)
392 g_string_append (buffer, "\n");
393
394 status = part->validity->encrypt.status;
395 desc = smime_encrypt_table[status].shortdesc;
396 g_string_append (buffer, gettext (desc));
397 }
398
399 description = g_string_free (buffer, FALSE);
400
401 /* FIXME: need to have it based on encryption and signing too */
402 if (part->validity->sign.status != 0)
403 icon_name = smime_sign_table[part->validity->sign.status].icon;
404 else
405 icon_name = smime_encrypt_table[part->validity->encrypt.status].icon;
406
407 box = gtk_event_box_new ();
408 if (part->validity->sign.status != 0)
409 gtk_widget_override_background_color (
410 box, GTK_STATE_FLAG_NORMAL,
411 &smime_sign_colour[part->validity->sign.status]);
412
413 layout = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
414 gtk_container_add (GTK_CONTAINER (box), layout);
415
416 button = gtk_button_new ();
417 gtk_box_pack_start (GTK_BOX (layout), button, FALSE, FALSE, 0);
418 g_signal_connect (
419 button, "clicked",
420 G_CALLBACK (secure_button_clicked_cb), part);
421
422 widget = gtk_image_new_from_icon_name (
423 icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
424 gtk_button_set_image (GTK_BUTTON (button), widget);
425
426 widget = gtk_label_new (description);
427 gtk_box_pack_start (GTK_BOX (layout), widget, FALSE, FALSE, 0);
428
429 gtk_widget_show_all (box);
430
431 g_free (description);
432 return box;
433 }
434
435 static const gchar *
436 emfe_secure_button_get_display_name (EMailFormatterExtension *extension)
437 {
438 return NULL;
439 }
440
441 static const gchar *
442 emfe_secure_button_get_description (EMailFormatterExtension *extension)
443 {
444 return NULL;
445 }
446
447 static const gchar **
448 emfe_secure_button_mime_types (EMailExtension *extension)
449 {
450 return formatter_mime_types;
451 }
452
453 static void
454 e_mail_formatter_secure_button_class_init (EMailFormatterSecureButtonClass *class)
455 {
456 }
457
458 static void
459 e_mail_formatter_formatter_extension_interface_init (EMailFormatterExtensionInterface *iface)
460 {
461 iface->format = emfe_secure_button_format;
462 iface->get_widget = emfe_secure_button_get_widget;
463 iface->get_display_name = emfe_secure_button_get_display_name;
464 iface->get_description = emfe_secure_button_get_description;
465 }
466
467 static void
468 e_mail_formatter_mail_extension_interface_init (EMailExtensionInterface *iface)
469 {
470 iface->mime_types = emfe_secure_button_mime_types;
471 }
472
473 static void
474 e_mail_formatter_secure_button_init (EMailFormatterSecureButton *extension)
475 {
476
477 }