2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2022 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/>.
20 #include "claws-features.h"
26 #include <glib/gi18n.h>
27 #include <gdk/gdkkeysyms.h>
28 #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 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
156 selector
= gtk_tree_view_get_selection(list_view
);
157 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
159 g_signal_connect(G_OBJECT(list_view
), "row_activated",
160 G_CALLBACK(ssl_manager_double_clicked
),
163 /* create the columns */
164 ssl_manager_create_list_view_columns(GTK_WIDGET(list_view
));
166 return GTK_WIDGET(list_view
);
170 *\brief Save Gtk object size to prefs dataset
172 static void ssl_manager_size_allocate_cb(GtkWidget
*widget
,
173 GtkAllocation
*allocation
)
175 cm_return_if_fail(allocation
!= NULL
);
177 gtk_window_get_size(GTK_WINDOW(widget
),
178 &prefs_common
.sslmanwin_width
, &prefs_common
.sslmanwin_height
);
181 void ssl_manager_create(void)
189 GtkWidget
*delete_btn
;
190 GtkWidget
*close_btn
;
191 static GdkGeometry geometry
;
193 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "ssl_manager");
194 gtk_window_set_title (GTK_WINDOW(window
),
195 _("Saved TLS certificates"));
197 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
198 gtk_window_set_position (GTK_WINDOW (window
), GTK_WIN_POS_CENTER
);
199 gtk_window_set_resizable(GTK_WINDOW (window
), TRUE
);
200 gtk_window_set_type_hint(GTK_WINDOW(window
), GDK_WINDOW_TYPE_HINT_DIALOG
);
201 g_signal_connect(G_OBJECT(window
), "delete_event",
202 G_CALLBACK(ssl_manager_close_cb
), NULL
);
203 g_signal_connect(G_OBJECT(window
), "size_allocate",
204 G_CALLBACK(ssl_manager_size_allocate_cb
), NULL
);
205 g_signal_connect(G_OBJECT(window
), "key_press_event",
206 G_CALLBACK(key_pressed
), NULL
);
207 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
209 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 6);
210 vbox1
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
211 delete_btn
= gtkut_stock_button("edit-delete", _("D_elete"));
213 g_signal_connect(G_OBJECT(delete_btn
), "clicked",
214 G_CALLBACK(ssl_manager_delete_cb
), NULL
);
216 view_btn
= gtkut_stock_button("dialog-information", _("_Information"));
217 g_signal_connect(G_OBJECT(view_btn
), "clicked",
218 G_CALLBACK(ssl_manager_view_cb
), NULL
);
220 close_btn
= gtk_button_new_with_mnemonic("_Close");
221 gtk_button_set_image(GTK_BUTTON(close_btn
),
222 gtk_image_new_from_icon_name("window-close", GTK_ICON_SIZE_BUTTON
));
223 g_signal_connect(G_OBJECT(close_btn
), "clicked",
224 G_CALLBACK(ssl_manager_close_cb
), NULL
);
226 certlist
= ssl_manager_list_view_create();
228 scroll
= gtk_scrolled_window_new (NULL
, NULL
);
229 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll
),
231 GTK_POLICY_AUTOMATIC
);
233 gtk_container_add(GTK_CONTAINER (scroll
), certlist
);
235 gtk_box_pack_start(GTK_BOX(hbox1
), scroll
, TRUE
, TRUE
, 0);
236 gtk_box_pack_start(GTK_BOX(hbox1
), vbox1
, FALSE
, FALSE
, 0);
237 gtk_box_pack_start(GTK_BOX(vbox1
), view_btn
, FALSE
, FALSE
, 4);
238 gtk_box_pack_start(GTK_BOX(vbox1
), delete_btn
, FALSE
, FALSE
, 4);
239 gtk_box_pack_end(GTK_BOX(vbox1
), close_btn
, FALSE
, FALSE
, 4);
241 if (!geometry
.min_height
) {
242 geometry
.min_width
= 700;
243 geometry
.min_height
= 250;
246 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
248 gtk_window_set_default_size(GTK_WINDOW(window
),
249 prefs_common
.sslmanwin_width
,
250 prefs_common
.sslmanwin_height
);
252 gtk_widget_show(certlist
);
253 gtk_widget_show(scroll
);
254 gtk_widget_show(hbox1
);
255 gtk_widget_show(vbox1
);
256 gtk_widget_show(close_btn
);
257 gtk_widget_show(delete_btn
);
258 gtk_widget_show(view_btn
);
259 gtk_container_add(GTK_CONTAINER (window
), hbox1
);
261 manager
.window
= window
;
262 manager
.hbox1
= hbox1
;
263 manager
.vbox1
= vbox1
;
264 manager
.certlist
= certlist
;
265 manager
.view_btn
= view_btn
;
266 manager
.delete_btn
= delete_btn
;
267 manager
.close_btn
= close_btn
;
269 gtk_widget_show(window
);
272 static void ssl_manager_list_view_insert_cert(GtkWidget
*list_view
,
273 GtkTreeIter
*row_iter
,
276 SSLCertificate
*cert
)
278 char *sig_status
, *exp_date
;
282 PangoWeight weight
= PANGO_WEIGHT_NORMAL
;
283 GtkTreeIter iter
, *iterptr
;
284 GtkListStore
*list_store
= GTK_LIST_STORE(gtk_tree_view_get_model
285 (GTK_TREE_VIEW(list_view
)));
287 g_return_if_fail(cert
!= NULL
);
289 exp_time_t
= gnutls_x509_crt_get_expiration_time(cert
->x509_cert
);
291 memset(buf
, 0, sizeof(buf
));
292 if (exp_time_t
> 0) {
293 fast_strftime(buf
, sizeof(buf
)-1, prefs_common
.date_format
, localtime_r(&exp_time_t
, <
));
294 exp_date
= (*buf
) ? g_strdup(buf
):g_strdup("?");
296 exp_date
= g_strdup("");
298 if (exp_time_t
< time(NULL
))
299 weight
= PANGO_WEIGHT_BOLD
;
301 sig_status
= ssl_certificate_check_signer(cert
, cert
->status
);
303 if (sig_status
== NULL
)
304 sig_status
= g_strdup_printf(_("Correct%s"),exp_time_t
< time(NULL
)? _(" (expired)"): "");
306 weight
= PANGO_WEIGHT_BOLD
;
307 if (exp_time_t
< time(NULL
))
308 sig_status
= g_strconcat(sig_status
,_(" (expired)"),NULL
);
311 if (row_iter
== NULL
) {
313 gtk_list_store_append(list_store
, &iter
);
318 gtk_list_store_set(list_store
, iterptr
,
319 SSL_MANAGER_HOST
, host
,
320 SSL_MANAGER_PORT
, port
,
321 SSL_MANAGER_CERT
, cert
,
322 SSL_MANAGER_STATUS
, sig_status
,
323 SSL_MANAGER_EXPIRY
, exp_date
,
324 SSL_MANAGER_FONT_WEIGHT
, weight
,
331 static void ssl_manager_load_certs (void)
335 GError
*error
= NULL
;
340 store
= GTK_LIST_STORE(gtk_tree_view_get_model
341 (GTK_TREE_VIEW(manager
.certlist
)));
343 gtk_list_store_clear(store
);
345 path
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
346 "certs", G_DIR_SEPARATOR_S
, NULL
);
348 if((dir
= g_dir_open(path
, 0, &error
)) == NULL
) {
349 debug_print("couldn't open dir '%s': %s (%d)\n", path
,
350 error
->message
, error
->code
);
356 while ((d
= g_dir_read_name(dir
)) != NULL
) {
357 gchar
*server
= NULL
, *port
= NULL
, *fp
= NULL
;
358 SSLCertificate
*cert
;
360 if(strstr(d
, ".cert") != d
+ (strlen(d
) - strlen(".cert")))
363 if (get_serverportfp_from_filename(d
, &server
, &port
, &fp
)) {
365 if (server
!= NULL
&& port
!= NULL
) {
366 gint portnum
= atoi(port
);
367 if (portnum
> 0 && portnum
<= 65535) {
368 cert
= ssl_certificate_find(server
, portnum
, fp
);
369 ssl_manager_list_view_insert_cert(manager
.certlist
, NULL
,
386 static void ssl_manager_close(void)
388 gtk_widget_hide(manager
.window
);
391 static void ssl_manager_close_cb(GtkWidget
*widget
,
397 static gboolean
key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
402 if (event
->keyval
== GDK_KEY_Escape
)
404 else if (event
->keyval
== GDK_KEY_Delete
)
405 ssl_manager_delete_cb(manager
.delete_btn
, NULL
);
410 static void ssl_manager_double_clicked(GtkTreeView
*list_view
,
412 GtkTreeViewColumn
*column
,
415 SSLCertificate
*cert
;
417 GtkTreeModel
*model
= gtk_tree_view_get_model(list_view
);
419 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
422 gtk_tree_model_get(model
, &iter
,
423 SSL_MANAGER_CERT
, &cert
,
429 sslcertwindow_show_cert(cert
);
436 static void ssl_manager_delete_cb(GtkWidget
*widget
,
439 SSLCertificate
*cert
;
444 cert
= gtkut_tree_view_get_selected_pointer(
445 GTK_TREE_VIEW(manager
.certlist
), SSL_MANAGER_CERT
,
446 &model
, NULL
, &iter
);
451 val
= alertpanel_full(_("Delete certificate"),
452 _("Do you really want to delete this certificate?"),
453 NULL
, _("_Cancel"), "edit-delete", _("D_elete"), NULL
, NULL
,
454 ALERTFOCUS_FIRST
, FALSE
, NULL
, ALERT_WARNING
);
457 if (val
!= G_ALERTALTERNATE
)
460 ssl_certificate_delete_from_disk(cert
);
461 ssl_certificate_destroy(cert
);
462 gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
465 static void ssl_manager_view_cb(GtkWidget
*widget
,
468 SSLCertificate
*cert
;
470 cert
= gtkut_tree_view_get_selected_pointer(
471 GTK_TREE_VIEW(manager
.certlist
), SSL_MANAGER_CERT
,
477 sslcertwindow_show_cert(cert
);