fix bug 4239, 'Preferences: Text Options Header Display modal is not modal' (sic)
[claws.git] / src / ssl_manager.c
index fb6c4c5642d602f858c078df787c286250b95b96..884a0225f35ced4c3d3cccfefec7ed5f3d2869fd 100644 (file)
@@ -41,6 +41,9 @@ enum {
        SSL_MANAGER_HOST,
        SSL_MANAGER_PORT,
        SSL_MANAGER_CERT,
+       SSL_MANAGER_STATUS,
+       SSL_MANAGER_EXPIRY,
+       SSL_MANAGER_FONT_WEIGHT,
        N_SSL_MANAGER_COLUMNS
 };
 
@@ -87,6 +90,9 @@ static GtkListStore* ssl_manager_create_data_store(void)
                                  G_TYPE_STRING,
                                  G_TYPE_STRING,
                                  G_TYPE_POINTER,
+                                 G_TYPE_STRING,
+                                 G_TYPE_STRING,
+                                 G_TYPE_INT,
                                  -1);
 }
 
@@ -96,20 +102,41 @@ static void ssl_manager_create_list_view_columns(GtkWidget *list_view)
        GtkCellRenderer *renderer;
 
        renderer = gtk_cell_renderer_text_new();
+       g_object_set(renderer, "weight", PANGO_WEIGHT_NORMAL,
+                            "weight-set", TRUE, NULL);
+
        column = gtk_tree_view_column_new_with_attributes
                (_("Server"),
                 renderer,
                 "text", SSL_MANAGER_HOST,
+                "weight", SSL_MANAGER_FONT_WEIGHT,
                 NULL);
-       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
+       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
 
-       renderer = gtk_cell_renderer_text_new();
        column = gtk_tree_view_column_new_with_attributes
                (_("Port"),
                 renderer,
                 "text", SSL_MANAGER_PORT,
                 NULL);
-       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
+       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+
+       column = gtk_tree_view_column_new_with_attributes
+               (_("Status"),
+                renderer,
+                "text", SSL_MANAGER_STATUS,
+                NULL);
+       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+
+       column = gtk_tree_view_column_new_with_attributes
+               (_("Expiry"),
+                renderer,
+                "text", SSL_MANAGER_EXPIRY,
+                NULL);
+       gtk_tree_view_column_set_attributes
+               (column, renderer,
+                "text", SSL_MANAGER_EXPIRY,
+                NULL);
+       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
 }
 
 static GtkWidget *ssl_manager_list_view_create (void)
@@ -137,7 +164,18 @@ static GtkWidget *ssl_manager_list_view_create     (void)
        ssl_manager_create_list_view_columns(GTK_WIDGET(list_view));
 
        return GTK_WIDGET(list_view);
+}
 
+/*!
+ *\brief       Save Gtk object size to prefs dataset
+ */
+static void ssl_manager_size_allocate_cb(GtkWidget *widget,
+                                        GtkAllocation *allocation)
+{
+       cm_return_if_fail(allocation != NULL);
+
+       prefs_common.sslmanwin_width = allocation->width;
+       prefs_common.sslmanwin_height = allocation->height;
 }
 
 void ssl_manager_create(void)
@@ -150,6 +188,7 @@ void ssl_manager_create(void)
        GtkWidget *view_btn;
        GtkWidget *delete_btn;
        GtkWidget *close_btn;
+       static GdkGeometry geometry;
 
        window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "ssl_manager");
        gtk_window_set_title (GTK_WINDOW(window),
@@ -158,8 +197,11 @@ void ssl_manager_create(void)
        gtk_container_set_border_width (GTK_CONTAINER (window), 8);
        gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
        gtk_window_set_resizable(GTK_WINDOW (window), TRUE);
+       gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG);
        g_signal_connect(G_OBJECT(window), "delete_event",
                         G_CALLBACK(ssl_manager_close_cb), NULL);
+       g_signal_connect(G_OBJECT(window), "size_allocate",
+                        G_CALLBACK(ssl_manager_size_allocate_cb), NULL);
        g_signal_connect(G_OBJECT(window), "key_press_event",
                         G_CALLBACK(key_pressed), NULL);
        MANAGE_WINDOW_SIGNALS_CONNECT (window);
@@ -185,6 +227,7 @@ void ssl_manager_create(void)
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
                                        GTK_POLICY_NEVER,
                                        GTK_POLICY_AUTOMATIC);
+
        gtk_container_add(GTK_CONTAINER (scroll), certlist);
 
        gtk_box_pack_start(GTK_BOX(hbox1), scroll, TRUE, TRUE, 0);
@@ -193,6 +236,16 @@ void ssl_manager_create(void)
        gtk_box_pack_start(GTK_BOX(vbox1), delete_btn, FALSE, FALSE, 4);
        gtk_box_pack_end(GTK_BOX(vbox1), close_btn, FALSE, FALSE, 4);
 
+       if (!geometry.min_height) {
+               geometry.min_width = 700;
+               geometry.min_height = 250;
+       }
+
+       gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
+                                     GDK_HINT_MIN_SIZE);
+       gtk_widget_set_size_request(window, prefs_common.sslmanwin_width,
+                                   prefs_common.sslmanwin_height);
+
        gtk_widget_show(certlist);
        gtk_widget_show(scroll);
        gtk_widget_show(hbox1);
@@ -213,96 +266,63 @@ void ssl_manager_create(void)
        gtk_widget_show(window);
 }
 
-static gboolean get_serverport(const gchar *str, gchar **server, gchar **port)
-{
-       const gchar *pos, *prevpos;
-
-       g_return_val_if_fail(str != NULL, FALSE);
-
-       for (prevpos = str, pos = strstr(str, ".") + 1;
-                       pos != NULL;
-                       prevpos = pos, pos = strstr(pos, ".") + 1) {
-               if (!strcmp(pos, "cert") || !strcmp(pos, "cert.chain")) {
-                       *server = strndup(str, prevpos - str - 1);
-                       *port = strndup(prevpos, pos - prevpos - 1);
-                       return TRUE;
-               }
-       }
-
-       return FALSE;
-}
-
-static char *get_port(const char *str)
-{
-       const char *pos, *prevpos;
-       char *port;
-
-       g_return_val_if_fail(str != NULL, NULL);
-
-       /* Iterate through all '.'-separated chunks, and the last one
-        * before the .cert or .cert.chain suffix is the port number. */
-       for (prevpos = str, pos = strstr(str, ".") + 1;
-                       pos != NULL;
-                       prevpos = pos, pos = strstr(pos, ".") + 1) {
-               if (!strcmp(pos, "cert") || !strcmp(pos, "cert.chain")) {
-                       port = strndup(prevpos, pos - prevpos - 1);
-                       return port;
-               }
-       }
-
-       return NULL;
-}
-
-static char *get_fingerprint(const char *str)
-{
-       char *ret = NULL, *tmp = g_strdup(str);
-       char *previous_pos = NULL, *last_pos = NULL;
-
-       if (!strchr(tmp, ':')) {
-               /* no fingerprint */
-               if (strstr(tmp, ".cert"))
-                       *(strstr(tmp, ".cert")+1) = '.';
-       }
-
-       while (tmp && (tmp = strstr(tmp,".")) != NULL) {
-               tmp++;
-               previous_pos = last_pos;
-               last_pos = tmp;
-       }
-       if (last_pos && previous_pos && (int)(last_pos - previous_pos - 1) > 0)
-               ret = g_strndup(previous_pos, (int)(last_pos - previous_pos - 1));
-       else
-               ret = NULL;
-       g_free(tmp);
-       return ret;
-       
-}
-
 static void ssl_manager_list_view_insert_cert(GtkWidget *list_view,
                                                  GtkTreeIter *row_iter,
                                                  gchar *host, 
                                                  gchar *port,
                                                  SSLCertificate *cert) 
 {
-       GtkTreeIter iter;
+       char *sig_status, *exp_date;
+       char buf[100];
+       time_t exp_time_t;
+       struct tm lt;
+       PangoWeight weight = PANGO_WEIGHT_NORMAL;
+       GtkTreeIter iter, *iterptr;
        GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model
                                        (GTK_TREE_VIEW(list_view)));
 
+       g_return_if_fail(cert != NULL);
+
+       exp_time_t = gnutls_x509_crt_get_expiration_time(cert->x509_cert);
+
+       memset(buf, 0, sizeof(buf));
+       if (exp_time_t > 0) {
+               fast_strftime(buf, sizeof(buf)-1, prefs_common.date_format, localtime_r(&exp_time_t, &lt));
+               exp_date = (*buf) ? g_strdup(buf):g_strdup("?");
+       } else
+               exp_date = g_strdup("");
+
+       if (exp_time_t < time(NULL))
+               weight = PANGO_WEIGHT_BOLD;
+
+       sig_status = ssl_certificate_check_signer(cert, cert->status);
+
+       if (sig_status == NULL)
+               sig_status = g_strdup_printf(_("Correct%s"),exp_time_t < time(NULL)? _(" (expired)"): "");
+       else {
+                weight = PANGO_WEIGHT_BOLD;
+                if (exp_time_t < time(NULL))
+                         sig_status = g_strconcat(sig_status,_(" (expired)"),NULL);
+       }
+
        if (row_iter == NULL) {
                /* append new */
                gtk_list_store_append(list_store, &iter);
-               gtk_list_store_set(list_store, &iter,
-                                  SSL_MANAGER_HOST, host,
-                                  SSL_MANAGER_PORT, port,
-                                  SSL_MANAGER_CERT, cert,
-                                  -1);
-       } else {
-               gtk_list_store_set(list_store, row_iter,
-                                  SSL_MANAGER_HOST, host,
-                                  SSL_MANAGER_PORT, port,
-                                  SSL_MANAGER_CERT, cert,
-                                  -1);
-       }
+               iterptr = &iter;
+       } else
+               iterptr = row_iter;
+
+       gtk_list_store_set(list_store, iterptr,
+                          SSL_MANAGER_HOST, host,
+                          SSL_MANAGER_PORT, port,
+                          SSL_MANAGER_CERT, cert,
+                          SSL_MANAGER_STATUS, sig_status,
+                          SSL_MANAGER_EXPIRY, exp_date,
+                          SSL_MANAGER_FONT_WEIGHT, weight,
+                          -1);
+
+       g_free(sig_status);
+       g_free(exp_date);
 }
 
 static void ssl_manager_load_certs (void) 
@@ -336,17 +356,21 @@ static void ssl_manager_load_certs (void)
                if(strstr(d, ".cert") != d + (strlen(d) - strlen(".cert"))) 
                        continue;
 
-               get_serverport(d, &server, &port);
-               fp = get_fingerprint(d);
-               
-               cert = ssl_certificate_find(server, atoi(port), fp);
+               if (get_serverportfp_from_filename(d, &server, &port, &fp)) {
 
-               ssl_manager_list_view_insert_cert(manager.certlist, NULL, 
-                                                 server, port, cert);
+                       if (server != NULL && port != NULL) {
+                               gint portnum = atoi(port);
+                               if (portnum > 0 && portnum <= 65535) {
+                                       cert = ssl_certificate_find(server, portnum, fp);
+                                       ssl_manager_list_view_insert_cert(manager.certlist, NULL,
+                                                       server, port, cert);
+                               }
+                       }
                
-               g_free(server);
-               g_free(port);
-               g_free(fp);
+                       g_free(server);
+                       g_free(port);
+                       g_free(fp);
+               }
                row++;
        }
        g_dir_close(dir);
@@ -366,8 +390,14 @@ static void ssl_manager_close_cb(GtkWidget *widget,
 
 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
-       if (event && event->keyval == GDK_KEY_Escape)
+       if (!event)
+               return FALSE;
+
+       if (event->keyval == GDK_KEY_Escape)
                ssl_manager_close();
+       else if (event->keyval == GDK_KEY_Delete)
+               ssl_manager_delete_cb(manager.delete_btn, NULL);
+
        return FALSE;
 }
 
@@ -402,24 +432,20 @@ static void ssl_manager_delete_cb(GtkWidget *widget,
 {
        SSLCertificate *cert;
        int val;
-       GtkTreeIter sel;
+       GtkTreeIter iter;
        GtkTreeModel *model;
 
-       if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection
-                               (GTK_TREE_VIEW(manager.certlist)),
-                               &model, &sel))
-               return;
-       
-       gtk_tree_model_get(model, &sel,
-                          SSL_MANAGER_CERT, &cert,
-                          -1);
+       cert = gtkut_tree_view_get_selected_pointer(
+                       GTK_TREE_VIEW(manager.certlist), SSL_MANAGER_CERT,
+                       &model, NULL, &iter);
+
        if (!cert)
                return;
 
        val = alertpanel_full(_("Delete certificate"),
                              _("Do you really want to delete this certificate?"),
-                             GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
-                             NULL, ALERT_WARNING, G_ALERTDEFAULT);
+                             GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, ALERTFOCUS_FIRST,
+                                               FALSE, NULL, ALERT_WARNING);
 
                             
        if (val != G_ALERTALTERNATE)
@@ -427,24 +453,18 @@ static void ssl_manager_delete_cb(GtkWidget *widget,
        
        ssl_certificate_delete_from_disk(cert);
        ssl_certificate_destroy(cert);
-       gtk_list_store_remove(GTK_LIST_STORE(model), &sel);
+       gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
 }
 
 static void ssl_manager_view_cb(GtkWidget *widget, 
                                gpointer data) 
 {
        SSLCertificate *cert;
-       GtkTreeIter sel;
-       GtkTreeModel *model;
 
-       if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection
-                               (GTK_TREE_VIEW(manager.certlist)),
-                               &model, &sel))
-               return;
-       
-       gtk_tree_model_get(model, &sel,
-                          SSL_MANAGER_CERT, &cert,
-                          -1);
+       cert = gtkut_tree_view_get_selected_pointer(
+                       GTK_TREE_VIEW(manager.certlist), SSL_MANAGER_CERT,
+                       NULL, NULL, NULL);
+
        if (!cert)
                return;