Maemo: Added a widget to "unselect" a certificate.
[strongswan.git] / src / frontends / maemo / src / strongswan-settings.c
1 /*
2 * Copyright (C) 2010 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <hildon-cp-plugin/hildon-cp-plugin-interface.h>
17 #include <gtk/gtk.h>
18 #include <hildon/hildon.h>
19 #include <hildon/hildon-file-chooser-dialog.h>
20
21 #include <string.h>
22
23 #include "strongswan-connections.h"
24
25 enum {
26 RESPONSE_NEW = 1,
27 RESPONSE_EDIT,
28 RESPONSE_DELETE
29 };
30
31 struct {
32 GtkWidget *dialog;
33 GtkWidget *list;
34 StrongswanConnections *conns;
35 } ListDialog = { 0, };
36
37 /**
38 * Callback if no certificate should be selected
39 */
40 void no_certificate(HildonButton *button, gpointer user_data)
41 {
42 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_REJECT);
43 }
44
45 /**
46 * Callback to select a certificate
47 */
48 void select_cert(HildonButton *button, gpointer user_data)
49 {
50 GtkWidget *selector = hildon_file_chooser_dialog_new (GTK_WINDOW (user_data), GTK_FILE_CHOOSER_ACTION_OPEN);
51 GtkWidget *nocert = hildon_button_new (HILDON_SIZE_FINGER_HEIGHT |
52 HILDON_SIZE_AUTO_WIDTH,
53 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
54 hildon_button_set_text (HILDON_BUTTON (nocert),
55 "No certificate",
56 "Use system-wide CA certificates");
57 hildon_button_set_alignment (HILDON_BUTTON (nocert), 0, 0.5, 1, 1);
58 g_signal_connect (nocert, "clicked", G_CALLBACK (no_certificate), selector);
59 hildon_file_chooser_dialog_add_extra (HILDON_FILE_CHOOSER_DIALOG (selector),
60 nocert);
61 gtk_widget_show_all (selector);
62
63 switch (gtk_dialog_run (GTK_DIALOG (selector)))
64 {
65 case GTK_RESPONSE_OK:
66 {
67 gchar *file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (selector));
68 hildon_button_set_value (button, file);
69 g_free(file);
70 break;
71 }
72 case GTK_RESPONSE_REJECT:
73 {
74 hildon_button_set_value (button, "None");
75 break;
76 }
77 default:
78 break;
79 }
80 gtk_widget_destroy (selector);
81 }
82
83 /**
84 * Shows a dialog to edit the given connection (or create a new one,
85 * if conn is NULL)
86 */
87 static void
88 edit_connection (gpointer *parent, StrongswanConnection *conn)
89 {
90 GtkWidget *dialog;
91 dialog = gtk_dialog_new_with_buttons (
92 conn ? "Edit Connection" : "New Connection",
93 GTK_WINDOW (parent),
94 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
95 GTK_STOCK_CANCEL,
96 GTK_RESPONSE_CANCEL,
97 GTK_STOCK_SAVE,
98 GTK_RESPONSE_OK,
99 NULL);
100 GtkWidget *vbox = GTK_DIALOG (dialog)->vbox;
101 GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
102
103 GtkWidget *name = hildon_entry_new (HILDON_SIZE_AUTO);
104 hildon_gtk_entry_set_placeholder_text (GTK_ENTRY (name), "Connection Name");
105 hildon_gtk_entry_set_input_mode (GTK_ENTRY (name),
106 HILDON_GTK_INPUT_MODE_AUTOCAP |
107 HILDON_GTK_INPUT_MODE_ALPHA |
108 HILDON_GTK_INPUT_MODE_NUMERIC);
109 GtkWidget *ncap = hildon_caption_new (group,
110 "Name",
111 name,
112 NULL,
113 HILDON_CAPTION_OPTIONAL);
114 gtk_box_pack_start (GTK_BOX (vbox), ncap, TRUE, TRUE, 0);
115
116 GtkWidget *host = hildon_entry_new (HILDON_SIZE_AUTO);
117 hildon_gtk_entry_set_placeholder_text (GTK_ENTRY (host), "Hostname / IP");
118 hildon_gtk_entry_set_input_mode (GTK_ENTRY (host),
119 HILDON_GTK_INPUT_MODE_FULL);
120 GtkWidget *hcap = hildon_caption_new (group,
121 "Host",
122 host,
123 NULL,
124 HILDON_CAPTION_OPTIONAL);
125 gtk_box_pack_start (GTK_BOX (vbox), hcap, TRUE, TRUE, 0);
126
127 GtkWidget *cert = hildon_button_new (HILDON_SIZE_FINGER_HEIGHT |
128 HILDON_SIZE_AUTO_WIDTH,
129 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
130 hildon_button_set_text (HILDON_BUTTON (cert),
131 "Host or CA Certificate",
132 "None");
133 hildon_button_set_alignment (HILDON_BUTTON (cert), 0, 0.5, 1, 1);
134 g_signal_connect (cert, "clicked", G_CALLBACK (select_cert), dialog);
135 GtkWidget *ccap = hildon_caption_new (group,
136 "Certificate",
137 cert,
138 NULL,
139 HILDON_CAPTION_OPTIONAL);
140 gtk_box_pack_start (GTK_BOX (vbox), ccap, TRUE, TRUE, 0);
141
142 GtkWidget *user = hildon_entry_new (HILDON_SIZE_AUTO);
143 hildon_gtk_entry_set_placeholder_text (GTK_ENTRY (user), "Username");
144 hildon_gtk_entry_set_input_mode (GTK_ENTRY (user),
145 HILDON_GTK_INPUT_MODE_FULL);
146 GtkWidget *ucap = hildon_caption_new (group,
147 "Username",
148 user,
149 NULL,
150 HILDON_CAPTION_OPTIONAL);
151 gtk_box_pack_start (GTK_BOX (vbox), ucap, TRUE, TRUE, 0);
152
153 if (conn)
154 {
155 gchar *c_name, *c_host, *c_cert, *c_user;
156 g_object_get (conn,
157 "name", &c_name,
158 "host", &c_host,
159 "cert", &c_cert,
160 "user", &c_user,
161 NULL);
162 gtk_entry_set_text (GTK_ENTRY (name), c_name);
163 gtk_entry_set_text (GTK_ENTRY (host), c_host);
164 hildon_button_set_value (HILDON_BUTTON (cert),
165 c_cert ? c_cert : "None");
166 gtk_entry_set_text (GTK_ENTRY (user), c_user);
167 g_free (c_name);
168 g_free (c_host);
169 g_free (c_cert);
170 g_free (c_user);
171 }
172
173 gtk_widget_show_all (dialog);
174
175 gint retval = gtk_dialog_run (GTK_DIALOG (dialog));
176 if (retval == GTK_RESPONSE_OK)
177 {
178 const gchar *c_name, *c_cert;
179 c_name = gtk_entry_get_text (GTK_ENTRY (name));
180 if (!conn)
181 {
182 conn = strongswan_connection_new (c_name);
183 }
184 c_cert = hildon_button_get_value (HILDON_BUTTON (cert));
185 c_cert = strcmp (c_cert, "None") ? c_cert : NULL;
186 g_object_set (conn,
187 "name", c_name,
188 "host", gtk_entry_get_text (GTK_ENTRY (host)),
189 "cert", c_cert,
190 "user", gtk_entry_get_text (GTK_ENTRY (user)),
191 NULL);
192 strongswan_connections_save_connection (ListDialog.conns, conn);
193 }
194 gtk_widget_destroy (dialog);
195 }
196
197 /**
198 * Creates a dialog showing a list of all connections
199 */
200 static void
201 create_list_dialog (gpointer *parent)
202 {
203 GtkWidget *dialog = gtk_dialog_new_with_buttons (
204 "strongSwan Connections",
205 GTK_WINDOW (parent),
206 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
207 GTK_STOCK_NEW,
208 RESPONSE_NEW,
209 GTK_STOCK_EDIT,
210 RESPONSE_EDIT,
211 GTK_STOCK_DELETE,
212 RESPONSE_DELETE,
213 GTK_STOCK_CLOSE,
214 GTK_RESPONSE_OK,
215 NULL);
216 ListDialog.dialog = dialog;
217 GtkWidget *vbox = GTK_DIALOG (dialog)->vbox;
218
219 ListDialog.conns = strongswan_connections_new ();
220
221 GtkTreeModel *model = strongswan_connections_get_model (ListDialog.conns);
222 ListDialog.list = gtk_tree_view_new_with_model (model);
223 g_object_unref (model);
224
225 GtkTreeSelection *selection;
226 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ListDialog.list));
227 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
228
229 GtkTreeViewColumn *column = gtk_tree_view_column_new ();
230 strongswan_connections_setup_column_renderers (ListDialog.conns,
231 GTK_CELL_LAYOUT (column));
232 gtk_tree_view_append_column (GTK_TREE_VIEW (ListDialog.list), column);
233
234 gtk_box_pack_start (GTK_BOX (vbox),
235 ListDialog.list,
236 TRUE,
237 TRUE,
238 HILDON_MARGIN_DEFAULT);
239 gtk_widget_show_all (dialog);
240 gtk_widget_hide (dialog);
241 }
242
243 /**
244 * Get the name fo the selected connection in the list (or NULL).
245 * The name has to be freed.
246 */
247 static gchar *
248 get_selected (void)
249 {
250 GtkTreeView *tree = GTK_TREE_VIEW(ListDialog.list);
251 GtkTreeSelection *selection;
252 GtkTreeModel *model;
253 GtkTreeIter iter;
254 gchar *name = NULL;
255
256 selection = gtk_tree_view_get_selection (tree);
257 model = gtk_tree_view_get_model (tree);
258 if (gtk_tree_selection_get_selected (selection, &model, &iter))
259 {
260 gtk_tree_model_get(model, &iter, 0, &name, -1);
261 }
262 return name;
263 }
264
265 /**
266 * main callback for control panel plugins
267 */
268 osso_return_t execute(osso_context_t *osso, gpointer data,
269 gboolean user_activated)
270 {
271 gint response;
272
273 create_list_dialog (data);
274
275 if (!user_activated)
276 {
277 /* load state */
278 }
279
280 do
281 {
282 gchar *selected;
283 response = gtk_dialog_run (GTK_DIALOG (ListDialog.dialog));
284 switch (response)
285 {
286 case RESPONSE_NEW:
287 {
288 edit_connection (data, NULL);
289 break;
290 }
291 case RESPONSE_EDIT:
292 {
293 StrongswanConnection *conn;
294 selected = get_selected ();
295 conn = strongswan_connections_get_connection (ListDialog.conns,
296 selected);
297 if (conn)
298 {
299 edit_connection (data, conn);
300 }
301 else
302 {
303 hildon_banner_show_information (NULL, NULL,
304 "Select a connection first");
305 }
306 g_free (selected);
307 break;
308 }
309 case RESPONSE_DELETE:
310 {
311 GtkWidget *confirm;
312 gint retval;
313 gchar *msg;
314 selected = get_selected ();
315 if (!selected)
316 {
317 hildon_banner_show_information (NULL, NULL,
318 "Select a connection first");
319 break;
320 }
321 msg = g_strdup_printf ("Delete connection?\n%s", selected);
322 confirm = hildon_note_new_confirmation (data, msg);
323 retval = gtk_dialog_run (GTK_DIALOG (confirm));
324 if (retval == GTK_RESPONSE_OK)
325 {
326 strongswan_connections_remove_connection (ListDialog.conns,
327 selected);
328 }
329 gtk_widget_destroy (confirm);
330 g_free (msg);
331 g_free (selected);
332 break;
333 }
334 default:
335 break;
336 }
337 }
338 while (response > 0);
339
340 gtk_widget_destroy (ListDialog.dialog);
341 g_object_unref (ListDialog.conns);
342 return OSSO_OK;
343 }
344
345 /**
346 * callback called in case state has to be saved
347 */
348 osso_return_t save_state(osso_context_t *osso, gpointer data)
349 {
350 /* save state */
351 return OSSO_OK;
352 }
353