2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2024 the Claws Mail team and Colin Leroy
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "claws-features.h"
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <sys/types.h>
31 #include "ssl_manager.h"
32 #include "ssl_certificate.h"
33 #include "manage_window.h"
35 #include "mainwindow.h"
36 #include "alertpanel.h"
37 #include "sslcertwindow.h"
38 #include "prefs_common.h"
46 SSL_MANAGER_FONT_WEIGHT
,
51 static struct SSLManager
58 GtkWidget
*delete_btn
;
62 static void ssl_manager_view_cb (GtkWidget
*widget
, gpointer data
);
63 static void ssl_manager_delete_cb (GtkWidget
*widget
, gpointer data
);
64 static void ssl_manager_close_cb (GtkWidget
*widget
, gpointer data
);
65 static gboolean
key_pressed (GtkWidget
*widget
, GdkEventKey
*event
,
67 static void ssl_manager_load_certs (void);
68 static void ssl_manager_double_clicked(GtkTreeView
*list_view
,
70 GtkTreeViewColumn
*column
,
73 void ssl_manager_open(MainWindow
*mainwin
)
78 manage_window_set_transient(GTK_WINDOW(manager
.window
));
79 gtk_widget_grab_focus(manager
.close_btn
);
81 ssl_manager_load_certs();
83 gtk_widget_show(manager
.window
);
87 static GtkListStore
* ssl_manager_create_data_store(void)
89 return gtk_list_store_new(N_SSL_MANAGER_COLUMNS
,
99 static void ssl_manager_create_list_view_columns(GtkWidget
*list_view
)
101 GtkTreeViewColumn
*column
;
102 GtkCellRenderer
*renderer
;
104 renderer
= gtk_cell_renderer_text_new();
105 g_object_set(renderer
, "weight", PANGO_WEIGHT_NORMAL
,
106 "weight-set", TRUE
, NULL
);
108 column
= gtk_tree_view_column_new_with_attributes
111 "text", SSL_MANAGER_HOST
,
112 "weight", SSL_MANAGER_FONT_WEIGHT
,
114 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
116 column
= gtk_tree_view_column_new_with_attributes
119 "text", SSL_MANAGER_PORT
,
121 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
123 column
= gtk_tree_view_column_new_with_attributes
126 "text", SSL_MANAGER_STATUS
,
128 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
130 column
= gtk_tree_view_column_new_with_attributes
133 "text", SSL_MANAGER_EXPIRY
,
135 gtk_tree_view_column_set_attributes
137 "text", SSL_MANAGER_EXPIRY
,
139 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
142 static GtkWidget
*ssl_manager_list_view_create (void)
144 GtkTreeView
*list_view
;
145 GtkTreeSelection
*selector
;
148 model
= GTK_TREE_MODEL(ssl_manager_create_data_store());
149 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(model
));
151 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model
),
152 0, GTK_SORT_ASCENDING
);
153 g_object_unref(model
);
154 selector
= gtk_tree_view_get_selection(list_view
);
155 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
157 g_signal_connect(G_OBJECT(list_view
), "row_activated",
158 G_CALLBACK(ssl_manager_double_clicked
),
161 /* create the columns */
162 ssl_manager_create_list_view_columns(GTK_WIDGET(list_view
));
164 return GTK_WIDGET(list_view
);
168 *\brief Save Gtk object size to prefs dataset
170 static void ssl_manager_size_allocate_cb(GtkWidget
*widget
,
171 GtkAllocation
*allocation
)
173 cm_return_if_fail(allocation
!= NULL
);
175 gtk_window_get_size(GTK_WINDOW(widget
),
176 &prefs_common
.sslmanwin_width
, &prefs_common
.sslmanwin_height
);
179 void ssl_manager_create(void)
187 GtkWidget
*delete_btn
;
188 GtkWidget
*close_btn
;
189 static GdkGeometry geometry
;
191 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "ssl_manager");
192 gtk_window_set_title (GTK_WINDOW(window
),
193 _("Saved TLS certificates"));
195 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
196 gtk_window_set_position (GTK_WINDOW (window
), GTK_WIN_POS_CENTER
);
197 gtk_window_set_resizable(GTK_WINDOW (window
), TRUE
);
198 gtk_window_set_type_hint(GTK_WINDOW(window
), GDK_WINDOW_TYPE_HINT_DIALOG
);
199 g_signal_connect(G_OBJECT(window
), "delete_event",
200 G_CALLBACK(ssl_manager_close_cb
), NULL
);
201 g_signal_connect(G_OBJECT(window
), "size_allocate",
202 G_CALLBACK(ssl_manager_size_allocate_cb
), NULL
);
203 g_signal_connect(G_OBJECT(window
), "key_press_event",
204 G_CALLBACK(key_pressed
), NULL
);
205 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
207 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 6);
208 vbox1
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
209 delete_btn
= gtkut_stock_button("edit-delete", _("D_elete"));
211 g_signal_connect(G_OBJECT(delete_btn
), "clicked",
212 G_CALLBACK(ssl_manager_delete_cb
), NULL
);
214 view_btn
= gtkut_stock_button("dialog-information", _("_Information"));
215 g_signal_connect(G_OBJECT(view_btn
), "clicked",
216 G_CALLBACK(ssl_manager_view_cb
), NULL
);
218 close_btn
= gtk_button_new_with_mnemonic(_("_Close"));
219 gtk_button_set_image(GTK_BUTTON(close_btn
),
220 gtk_image_new_from_icon_name("window-close", GTK_ICON_SIZE_BUTTON
));
221 g_signal_connect(G_OBJECT(close_btn
), "clicked",
222 G_CALLBACK(ssl_manager_close_cb
), NULL
);
224 certlist
= ssl_manager_list_view_create();
226 scroll
= gtk_scrolled_window_new (NULL
, NULL
);
227 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll
),
229 GTK_POLICY_AUTOMATIC
);
231 gtk_container_add(GTK_CONTAINER (scroll
), certlist
);
233 gtk_box_pack_start(GTK_BOX(hbox1
), scroll
, TRUE
, TRUE
, 0);
234 gtk_box_pack_start(GTK_BOX(hbox1
), vbox1
, FALSE
, FALSE
, 0);
235 gtk_box_pack_start(GTK_BOX(vbox1
), view_btn
, FALSE
, FALSE
, 4);
236 gtk_box_pack_start(GTK_BOX(vbox1
), delete_btn
, FALSE
, FALSE
, 4);
237 gtk_box_pack_end(GTK_BOX(vbox1
), close_btn
, FALSE
, FALSE
, 4);
239 if (!geometry
.min_height
) {
240 geometry
.min_width
= 700;
241 geometry
.min_height
= 250;
244 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
246 gtk_window_set_default_size(GTK_WINDOW(window
),
247 prefs_common
.sslmanwin_width
,
248 prefs_common
.sslmanwin_height
);
250 gtk_widget_show(certlist
);
251 gtk_widget_show(scroll
);
252 gtk_widget_show(hbox1
);
253 gtk_widget_show(vbox1
);
254 gtk_widget_show(close_btn
);
255 gtk_widget_show(delete_btn
);
256 gtk_widget_show(view_btn
);
257 gtk_container_add(GTK_CONTAINER (window
), hbox1
);
259 manager
.window
= window
;
260 manager
.hbox1
= hbox1
;
261 manager
.vbox1
= vbox1
;
262 manager
.certlist
= certlist
;
263 manager
.view_btn
= view_btn
;
264 manager
.delete_btn
= delete_btn
;
265 manager
.close_btn
= close_btn
;
267 gtk_widget_show(window
);
270 static void ssl_manager_list_view_insert_cert(GtkWidget
*list_view
,
271 GtkTreeIter
*row_iter
,
274 SSLCertificate
*cert
)
276 char *sig_status
, *exp_date
;
280 PangoWeight weight
= PANGO_WEIGHT_NORMAL
;
281 GtkTreeIter iter
, *iterptr
;
282 GtkListStore
*list_store
= GTK_LIST_STORE(gtk_tree_view_get_model
283 (GTK_TREE_VIEW(list_view
)));
285 g_return_if_fail(cert
!= NULL
);
287 exp_time_t
= gnutls_x509_crt_get_expiration_time(cert
->x509_cert
);
289 memset(buf
, 0, sizeof(buf
));
290 if (exp_time_t
> 0) {
291 fast_strftime(buf
, sizeof(buf
)-1, prefs_common
.date_format
, localtime_r(&exp_time_t
, <
));
292 exp_date
= (*buf
) ? g_strdup(buf
):g_strdup("?");
294 exp_date
= g_strdup("");
296 if (exp_time_t
< time(NULL
))
297 weight
= PANGO_WEIGHT_BOLD
;
299 sig_status
= ssl_certificate_check_signer(cert
, cert
->status
);
301 if (sig_status
== NULL
)
302 sig_status
= g_strdup_printf(_("Correct%s"),exp_time_t
< time(NULL
)? _(" (expired)"): "");
304 weight
= PANGO_WEIGHT_BOLD
;
305 if (exp_time_t
< time(NULL
))
306 sig_status
= g_strconcat(sig_status
,_(" (expired)"),NULL
);
309 if (row_iter
== NULL
) {
311 gtk_list_store_append(list_store
, &iter
);
316 gtk_list_store_set(list_store
, iterptr
,
317 SSL_MANAGER_HOST
, host
,
318 SSL_MANAGER_PORT
, port
,
319 SSL_MANAGER_CERT
, cert
,
320 SSL_MANAGER_STATUS
, sig_status
,
321 SSL_MANAGER_EXPIRY
, exp_date
,
322 SSL_MANAGER_FONT_WEIGHT
, weight
,
329 static void ssl_manager_load_certs (void)
333 GError
*error
= NULL
;
338 store
= GTK_LIST_STORE(gtk_tree_view_get_model
339 (GTK_TREE_VIEW(manager
.certlist
)));
341 gtk_list_store_clear(store
);
343 path
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
344 "certs", G_DIR_SEPARATOR_S
, NULL
);
346 if((dir
= g_dir_open(path
, 0, &error
)) == NULL
) {
347 debug_print("couldn't open dir '%s': %s (%d)\n", path
,
348 error
->message
, error
->code
);
354 while ((d
= g_dir_read_name(dir
)) != NULL
) {
355 gchar
*server
= NULL
, *port
= NULL
, *fp
= NULL
;
356 SSLCertificate
*cert
;
358 if(strstr(d
, ".cert") != d
+ (strlen(d
) - strlen(".cert")))
361 if (get_serverportfp_from_filename(d
, &server
, &port
, &fp
)) {
363 if (server
!= NULL
&& port
!= NULL
) {
364 gint portnum
= atoi(port
);
365 if (portnum
> 0 && portnum
<= 65535) {
366 cert
= ssl_certificate_find(server
, portnum
, fp
);
367 ssl_manager_list_view_insert_cert(manager
.certlist
, NULL
,
384 static void ssl_manager_close(void)
386 gtk_widget_hide(manager
.window
);
389 static void ssl_manager_close_cb(GtkWidget
*widget
,
395 static gboolean
key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
400 if (event
->keyval
== GDK_KEY_Escape
)
402 else if (event
->keyval
== GDK_KEY_Delete
)
403 ssl_manager_delete_cb(manager
.delete_btn
, NULL
);
408 static void ssl_manager_double_clicked(GtkTreeView
*list_view
,
410 GtkTreeViewColumn
*column
,
413 SSLCertificate
*cert
;
415 GtkTreeModel
*model
= gtk_tree_view_get_model(list_view
);
417 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
420 gtk_tree_model_get(model
, &iter
,
421 SSL_MANAGER_CERT
, &cert
,
427 sslcertwindow_show_cert(cert
);
434 static void ssl_manager_delete_cb(GtkWidget
*widget
,
437 SSLCertificate
*cert
;
442 cert
= gtkut_tree_view_get_selected_pointer(
443 GTK_TREE_VIEW(manager
.certlist
), SSL_MANAGER_CERT
,
444 &model
, NULL
, &iter
);
449 val
= alertpanel_full(_("Delete certificate"),
450 _("Do you really want to delete this certificate?"),
451 NULL
, _("_Cancel"), "edit-delete", _("D_elete"), NULL
, NULL
,
452 ALERTFOCUS_FIRST
, FALSE
, NULL
, ALERT_WARNING
);
455 if (val
!= G_ALERTALTERNATE
)
458 ssl_certificate_delete_from_disk(cert
);
459 ssl_certificate_destroy(cert
);
460 gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
463 static void ssl_manager_view_cb(GtkWidget
*widget
,
466 SSLCertificate
*cert
;
468 cert
= gtkut_tree_view_get_selected_pointer(
469 GTK_TREE_VIEW(manager
.certlist
), SSL_MANAGER_CERT
,
475 sslcertwindow_show_cert(cert
);