evolution-3.6.4/smime/gui/e-cert-selector.c

No issues found

  1 /*
  2  *
  3  * This program is free software; you can redistribute it and/or
  4  * modify it under the terms of the GNU Lesser General Public
  5  * License as published by the Free Software Foundation; either
  6  * version 2 of the License, or (at your option) version 3.
  7  *
  8  * This program is distributed in the hope that it will be useful,
  9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 11  * Lesser General Public License for more details.
 12  *
 13  * You should have received a copy of the GNU Lesser General Public
 14  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 15  *
 16  *
 17  * Authors:
 18  *		Michael Zucchi <notzed@ximian.com>
 19  *
 20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 21  *
 22  */
 23 
 24 #ifdef HAVE_CONFIG_H
 25 #include <config.h>
 26 #endif
 27 
 28 #include <glib/gi18n.h>
 29 
 30 #include "nss.h"
 31 #include "pk11func.h"
 32 #include "certdb.h"
 33 #include "cert.h"
 34 
 35 #include "e-cert-selector.h"
 36 
 37 #include "e-util/e-util.h"
 38 #include "e-util/e-util-private.h"
 39 
 40 #define E_CERT_SELECTOR_GET_PRIVATE(obj) \
 41 	(G_TYPE_INSTANCE_GET_PRIVATE \
 42 	((obj), E_TYPE_CERT_SELECTOR, ECertSelectorPrivate))
 43 
 44 struct _ECertSelectorPrivate {
 45 	CERTCertList *certlist;
 46 
 47 	GtkWidget *combobox, *description;
 48 };
 49 
 50 enum {
 51 	ECS_SELECTED,
 52 	ECS_LAST_SIGNAL
 53 };
 54 
 55 static guint ecs_signals[ECS_LAST_SIGNAL];
 56 
 57 G_DEFINE_TYPE (ECertSelector, e_cert_selector, GTK_TYPE_DIALOG)
 58 
 59 /* (this is what mozilla shows)
 60  * Issued to:
 61  *  Subject: E=notzed@ximian.com, CN=notzed@ximian.com, O=My Company Ltd, L=Adelaide, ST=SA, C=AU
 62  *  Serial Number: 03
 63  *  Valid from 23/10/03 06:35:29 to 22/10/04 06:35:29
 64  *  Purposes: Sign,Encrypt
 65  * Issued by:
 66  *  Subject: E=notzed@ximian.com, O=company, L=there, ST=Here, C=AU
 67  */
 68 
 69 static CERTCertListNode *
 70 ecs_find_current (ECertSelector *ecs)
 71 {
 72 	struct _ECertSelectorPrivate *p = ecs->priv;
 73 	CERTCertListNode *node;
 74 	gint n;
 75 
 76 	if (p->certlist == NULL || CERT_LIST_EMPTY (p->certlist))
 77 		return NULL;
 78 
 79 	n = gtk_combo_box_get_active (GTK_COMBO_BOX (p->combobox));
 80 	node = CERT_LIST_HEAD (p->certlist);
 81 	while (n > 0 && !CERT_LIST_END (node, p->certlist)) {
 82 		n--;
 83 		node = CERT_LIST_NEXT (node);
 84 	}
 85 
 86 	g_return_val_if_fail (!CERT_LIST_END (node, p->certlist), NULL);
 87 
 88 	return node;
 89 }
 90 
 91 static void
 92 e_cert_selector_response (GtkDialog *dialog,
 93                           gint button)
 94 {
 95 	CERTCertListNode *node;
 96 
 97 	switch (button) {
 98 	case GTK_RESPONSE_OK:
 99 		node = ecs_find_current ((ECertSelector *) dialog);
100 		break;
101 	default:
102 		node = NULL;
103 		break;
104 	}
105 
106 	g_signal_emit (dialog, ecs_signals[ECS_SELECTED], 0, node ? node->cert->nickname : NULL);
107 }
108 
109 static void
110 ecs_cert_changed (GtkWidget *w,
111                   ECertSelector *ecs)
112 {
113 	struct _ECertSelectorPrivate *p = ecs->priv;
114 	CERTCertListNode *node;
115 	GtkTextBuffer *buffer;
116 	GString *text;
117 
118 	text = g_string_new ("");
119 	node = ecs_find_current (ecs);
120 	if (node) {
121 		/* FIXME: add serial no, validity date, uses */
122 		g_string_append_printf (text, _("Issued to:\n  Subject: %s\n"), node->cert->subjectName);
123 		g_string_append_printf (text, _("Issued by:\n  Subject: %s\n"), node->cert->issuerName);
124 	}
125 
126 	buffer = gtk_text_view_get_buffer ((GtkTextView *) p->description);
127 	gtk_text_buffer_set_text (buffer, text->str, text->len);
128 	g_string_free (text, TRUE);
129 }
130 
131 /**
132  * e_cert_selector_new:
133  * @type:
134  * @currentid:
135  *
136  * Create a new ECertSelector dialog.  @type specifies which type of cert to
137  * be selected, E_CERT_SELECTOR_SIGNER for signing certs, and
138  * E_CERT_SELECTOR_RECIPIENT for encrypting certs.
139  *
140  * @currentid is the nickname of the cert currently selected for this user.
141  *
142  * You only need to connect to a single signal "selected" which will
143  * be called with either a NULL nickname if cancelled, or the newly
144  * selected nickname otherwise.
145  *
146  * Return value: A dialogue to be shown.
147  **/
148 GtkWidget *
149 e_cert_selector_new (gint type,
150                      const gchar *currentid)
151 {
152 	ECertSelector *ecs;
153 	struct _ECertSelectorPrivate *p;
154 	SECCertUsage usage;
155 	CERTCertList *certlist;
156 	CERTCertListNode *node;
157 	GtkBuilder *builder;
158 	GtkWidget *content_area;
159 	GtkWidget *w;
160 	GtkListStore *store;
161 	GtkTreeIter iter;
162 	gint n = 0, active = 0;
163 
164 	ecs = g_object_new (e_cert_selector_get_type (), NULL);
165 	p = ecs->priv;
166 
167 	builder = gtk_builder_new ();
168 	e_load_ui_builder_definition (builder, "smime-ui.ui");
169 
170 	p->combobox = e_builder_get_widget (builder, "cert_combobox");
171 	p->description = e_builder_get_widget (builder, "cert_description");
172 
173 	w = e_builder_get_widget (builder, "cert_selector_vbox");
174 	content_area = gtk_dialog_get_content_area (GTK_DIALOG (ecs));
175 	gtk_box_pack_start (GTK_BOX (content_area), w, TRUE, TRUE, 3);
176 	gtk_window_set_title (GTK_WINDOW (ecs), _("Select certificate"));
177 
178 	switch (type) {
179 	case E_CERT_SELECTOR_SIGNER:
180 	default:
181 		usage = certUsageEmailSigner;
182 		break;
183 	case E_CERT_SELECTOR_RECIPIENT:
184 		usage = certUsageEmailRecipient;
185 		break;
186 	}
187 
188 	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (p->combobox)));
189 	gtk_list_store_clear (store);
190 
191 	certlist = CERT_FindUserCertsByUsage (CERT_GetDefaultCertDB (), usage, FALSE, TRUE, NULL);
192 	ecs->priv->certlist = certlist;
193 	if (certlist != NULL) {
194 		node = CERT_LIST_HEAD (certlist);
195 		while (!CERT_LIST_END (node, certlist)) {
196 			if (node->cert->nickname || node->cert->emailAddr) {
197 				gtk_list_store_append (store, &iter);
198 				gtk_list_store_set (
199 					store, &iter,
200 					0, node->cert->nickname ? node->cert->nickname : node->cert->emailAddr,
201 					-1);
202 
203 				if (currentid != NULL
204 				    && ((node->cert->nickname != NULL && strcmp (node->cert->nickname, currentid) == 0)
205 					|| (node->cert->emailAddr != NULL && strcmp (node->cert->emailAddr, currentid) == 0)))
206 					active = n;
207 
208 				n++;
209 			}
210 
211 			node = CERT_LIST_NEXT (node);
212 		}
213 	}
214 
215 	gtk_combo_box_set_active (GTK_COMBO_BOX (p->combobox), active);
216 
217 	g_signal_connect (
218 		p->combobox, "changed",
219 		G_CALLBACK (ecs_cert_changed), ecs);
220 
221 	g_object_unref (builder);
222 
223 	ecs_cert_changed (p->combobox, ecs);
224 
225 	return GTK_WIDGET (ecs);
226 }
227 
228 static void
229 e_cert_selector_init (ECertSelector *ecs)
230 {
231 	gtk_dialog_add_buttons (
232 		GTK_DIALOG (ecs),
233 		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
234 		GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
235 
236 	ecs->priv = E_CERT_SELECTOR_GET_PRIVATE (ecs);
237 }
238 
239 static void
240 e_cert_selector_finalize (GObject *object)
241 {
242 	ECertSelectorPrivate *priv;
243 
244 	priv = E_CERT_SELECTOR_GET_PRIVATE (object);
245 
246 	if (priv->certlist)
247 		CERT_DestroyCertList (priv->certlist);
248 
249 	/* Chain up to parent's finalize() method. */
250 	G_OBJECT_CLASS (e_cert_selector_parent_class)->finalize (object);
251 }
252 
253 static void
254 e_cert_selector_class_init (ECertSelectorClass *class)
255 {
256 	GObjectClass *object_class;
257 	GtkDialogClass *dialog_class;
258 
259 	g_type_class_add_private (class, sizeof (ECertSelectorPrivate));
260 
261 	object_class = G_OBJECT_CLASS (class);
262 	object_class->finalize = e_cert_selector_finalize;
263 
264 	dialog_class = GTK_DIALOG_CLASS (class);
265 	dialog_class->response = e_cert_selector_response;
266 
267 	ecs_signals[ECS_SELECTED] = g_signal_new (
268 		"selected",
269 		G_OBJECT_CLASS_TYPE (class),
270 		G_SIGNAL_RUN_LAST,
271 		G_STRUCT_OFFSET (ECertSelectorClass, selected),
272 		NULL, NULL,
273 		g_cclosure_marshal_VOID__POINTER,
274 		G_TYPE_NONE, 1,
275 		G_TYPE_POINTER);
276 }