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 }