2 * Copyright (C) 2010 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
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>.
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
16 #include <hildon/hildon.h>
21 #include "strongswan-status.h"
22 #include "strongswan-connections.h"
24 #define STRONGSWAN_STATUS_GET_PRIVATE(object) \
25 (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
26 STRONGSWAN_TYPE_STATUS, \
27 StrongswanStatusPrivate))
29 #define OSSO_STATUS_NAME "status"
30 #define OSSO_STATUS_SERVICE "org.strongswan."OSSO_STATUS_NAME
31 #define OSSO_STATUS_OBJECT "/org/strongswan/"OSSO_STATUS_NAME
32 #define OSSO_STATUS_IFACE "org.strongswan."OSSO_STATUS_NAME
34 #define OSSO_CHARON_NAME "charon"
35 #define OSSO_CHARON_SERVICE "org.strongswan."OSSO_CHARON_NAME
36 #define OSSO_CHARON_OBJECT "/org/strongswan/"OSSO_CHARON_NAME
37 #define OSSO_CHARON_IFACE "org.strongswan."OSSO_CHARON_NAME
39 #define ICON_SIZE_STATUS 18
40 #define ICON_SIZE_BUTTON 48
47 } StrongswanConnectionStatus
;
49 struct _StrongswanStatusPrivate
52 GdkPixbuf
*status_open
;
53 GdkPixbuf
*status_close
;
54 GdkPixbuf
*button_open
;
55 GdkPixbuf
*button_close
;
64 osso_context_t
*context
;
66 StrongswanConnections
*conns
;
68 StrongswanConnectionStatus status
;
72 HD_DEFINE_PLUGIN_MODULE_EXTENDED (StrongswanStatus
, strongswan_status
, \
73 HD_TYPE_STATUS_MENU_ITEM
, {}, { \
74 strongswan_connection_register (G_TYPE_MODULE (plugin
)); \
75 strongswan_connections_register (G_TYPE_MODULE (plugin
)); }, {});
78 update_status_menu (StrongswanStatus
*plugin
)
80 StrongswanStatusPrivate
*priv
= plugin
->priv
;
83 case STATUS_DISCONNECTED
:
85 hildon_button_set_value (HILDON_BUTTON (priv
->button
),
87 hd_status_plugin_item_set_status_area_icon (
88 HD_STATUS_PLUGIN_ITEM (plugin
),
89 priv
->icons
.status_open
);
90 gtk_image_set_from_pixbuf (GTK_IMAGE (priv
->image
),
91 priv
->icons
.button_open
);
94 case STATUS_CONNECTING
:
96 gchar
*msg
= g_strdup_printf ("Connecting to %s...", priv
->current
);
97 hildon_button_set_value (HILDON_BUTTON (priv
->button
), msg
);
101 case STATUS_CONNECTED
:
103 gchar
*msg
= g_strdup_printf ("Connected to %s", priv
->current
);
104 hildon_button_set_value (HILDON_BUTTON (priv
->button
), msg
);
106 hd_status_plugin_item_set_status_area_icon (
107 HD_STATUS_PLUGIN_ITEM (plugin
),
108 priv
->icons
.status_close
);
109 gtk_image_set_from_pixbuf (GTK_IMAGE (priv
->image
),
110 priv
->icons
.button_close
);
117 update_dialog_connecting (StrongswanStatus
*plugin
)
119 StrongswanStatusPrivate
*priv
= plugin
->priv
;
121 gtk_widget_set_sensitive (priv
->box
, FALSE
);
122 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv
->dialog
), 1);
126 update_dialog_default (StrongswanStatus
*plugin
)
128 StrongswanStatusPrivate
*priv
= plugin
->priv
;
130 gtk_widget_set_sensitive (priv
->box
, TRUE
);
131 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv
->dialog
), 0);
135 dialog_response (GtkDialog
*dialog
, gint response_id
, StrongswanStatus
*plugin
)
137 StrongswanStatusPrivate
*priv
= plugin
->priv
;
138 gtk_widget_destroy (priv
->dialog
);
143 connect_callback (const gchar
* interface
, const gchar
* method
,
144 osso_rpc_t
*retval
, StrongswanStatus
*plugin
)
147 StrongswanStatusPrivate
*priv
= plugin
->priv
;
149 if (retval
->type
== DBUS_TYPE_STRING
)
150 { /* unfortunately, this is the only indication that an error occured
151 * for asynchronous calls */
152 msg
= g_strdup_printf ("Failed to initiate connection: %s",
155 else if (retval
->type
!= DBUS_TYPE_BOOLEAN
)
157 msg
= g_strdup_printf ("Failed to initiate connection: return type");
159 else if (!retval
->value
.b
)
161 msg
= g_strdup_printf ("Failed to connect to %s", priv
->current
);
166 /* connecting failed */
167 priv
->current
= (g_free (priv
->current
), NULL
);
168 priv
->status
= STATUS_DISCONNECTED
;
172 msg
= g_strdup_printf ("Successfully connected to %s", priv
->current
);
173 priv
->status
= STATUS_CONNECTED
;
176 hildon_banner_show_information (NULL
, NULL
, msg
);
179 update_status_menu (plugin
);
183 update_dialog_default (plugin
);
184 gtk_dialog_response (GTK_DIALOG (priv
->dialog
), GTK_RESPONSE_OK
);
189 get_password (StrongswanStatus
*plugin
, gchar
**password
)
191 StrongswanStatusPrivate
*priv
= plugin
->priv
;
192 gboolean result
= FALSE
;
194 GtkWidget
*dialog
= gtk_dialog_new_with_buttons (
196 GTK_WINDOW(priv
->dialog
),
197 GTK_DIALOG_MODAL
| GTK_DIALOG_NO_SEPARATOR
,
203 GtkWidget
*vbox
= GTK_DIALOG (dialog
)->vbox
;
204 GtkSizeGroup
*group
= gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL
);
206 GtkWidget
*pass
= hildon_entry_new (HILDON_SIZE_AUTO
);
207 hildon_gtk_entry_set_placeholder_text (GTK_ENTRY (pass
), "Password");
208 hildon_gtk_entry_set_input_mode (GTK_ENTRY (pass
),
209 HILDON_GTK_INPUT_MODE_FULL
|
210 HILDON_GTK_INPUT_MODE_INVISIBLE
);
211 GtkWidget
*pcap
= hildon_caption_new (group
,
215 HILDON_CAPTION_OPTIONAL
);
216 gtk_box_pack_start (GTK_BOX (vbox
), pcap
, TRUE
, TRUE
, 0);
217 gtk_widget_show_all (dialog
);
219 gint retval
= gtk_dialog_run (GTK_DIALOG (dialog
));
220 if (retval
== GTK_RESPONSE_OK
)
222 *password
= g_strdup (gtk_entry_get_text (GTK_ENTRY (pass
)));
225 gtk_widget_destroy (dialog
);
230 connect_clicked (HildonButton
*button
, StrongswanStatus
*plugin
)
232 StrongswanStatusPrivate
*priv
= plugin
->priv
;
234 priv
->current
= hildon_touch_selector_get_current_text (
235 HILDON_TOUCH_SELECTOR (priv
->selector
));
236 priv
->status
= STATUS_CONNECTING
;
237 update_dialog_connecting (plugin
);
238 update_status_menu (plugin
);
240 StrongswanConnection
*conn
= strongswan_connections_get_connection (
244 { /* emulate a callback call */
246 retval
.type
= DBUS_TYPE_STRING
;
247 retval
.value
.s
= g_strdup ("not found");
248 connect_callback (NULL
, NULL
, &retval
, plugin
);
249 osso_rpc_free_val (&retval
);
253 /* this call on the system bus is only needed to start charon as root */
255 osso_return_t result
;
256 result
= osso_rpc_run_system (priv
->context
,
263 osso_rpc_free_val (&retval
);
264 if (result
!= OSSO_OK
)
266 retval
.type
= DBUS_TYPE_STRING
;
267 retval
.value
.s
= g_strdup ("couldn't connect to charon");
268 connect_callback (NULL
, NULL
, &retval
, plugin
);
269 osso_rpc_free_val (&retval
);
273 gchar
*c_host
, *c_cert
, *c_user
, *c_pass
;
275 if (!get_password (plugin
, &c_pass
))
277 update_dialog_default (plugin
);
287 osso_rpc_async_run (priv
->context
,
292 (osso_rpc_async_f
*)connect_callback
,
294 DBUS_TYPE_STRING
, priv
->current
,
295 DBUS_TYPE_STRING
, c_host
,
296 DBUS_TYPE_STRING
, c_cert
,
297 DBUS_TYPE_STRING
, c_user
,
298 DBUS_TYPE_STRING
, c_pass
,
308 disconnect_clicked (HildonButton
*button
, StrongswanStatus
*plugin
)
310 osso_return_t result
;
313 StrongswanStatusPrivate
*priv
= plugin
->priv
;
315 gtk_widget_set_sensitive (priv
->box
, FALSE
);
316 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv
->dialog
), 1);
318 result
= osso_rpc_run_system (priv
->context
,
326 gtk_widget_set_sensitive (priv
->box
, TRUE
);
327 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv
->dialog
), 0);
329 if (result
== OSSO_OK
)
331 msg
= g_strdup_printf ("Successfully disconnected from %s",
336 msg
= g_strdup_printf ("Failed to disconnect from %s", priv
->current
);
338 hildon_banner_show_information (NULL
, NULL
, msg
);
341 priv
->current
= (g_free (priv
->current
), NULL
);
342 priv
->status
= STATUS_DISCONNECTED
;
344 update_status_menu (plugin
);
346 gtk_dialog_response (GTK_DIALOG (priv
->dialog
), GTK_RESPONSE_OK
);
350 setup_dialog_disconnected (StrongswanStatus
*plugin
)
352 StrongswanStatusPrivate
*priv
= plugin
->priv
;
354 GtkWidget
*vbox
= GTK_DIALOG (priv
->dialog
)->vbox
;
355 GtkWidget
*hbox
= gtk_hbox_new (FALSE
, 0);
357 GtkWidget
*button
= hildon_picker_button_new (
358 HILDON_SIZE_FINGER_HEIGHT
|
359 HILDON_SIZE_AUTO_WIDTH
,
360 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL
);
361 hildon_button_set_title (HILDON_BUTTON (button
), "Connection:");
362 gtk_box_pack_start (GTK_BOX (hbox
), button
, TRUE
, TRUE
, 0);
364 GtkWidget
*selector
= hildon_touch_selector_new ();
365 priv
->selector
= selector
;
366 GtkTreeModel
*model
= strongswan_connections_get_model (priv
->conns
);
367 hildon_touch_selector_append_text_column (
368 HILDON_TOUCH_SELECTOR (selector
),
371 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button
),
372 HILDON_TOUCH_SELECTOR (selector
));
374 button
= hildon_button_new_with_text (
375 HILDON_SIZE_FINGER_HEIGHT
|
376 HILDON_SIZE_AUTO_WIDTH
,
377 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL
,
379 gtk_box_pack_start (GTK_BOX (hbox
), button
, FALSE
, FALSE
, 0);
380 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
381 g_signal_connect (button
, "clicked", G_CALLBACK (connect_clicked
),
386 setup_dialog_connected (StrongswanStatus
*plugin
)
388 StrongswanStatusPrivate
*priv
= plugin
->priv
;
390 GtkWidget
*vbox
= GTK_DIALOG (priv
->dialog
)->vbox
;
391 GtkWidget
*hbox
= gtk_hbox_new (FALSE
, 0);
393 GtkWidget
*button
= hildon_button_new_with_text (
394 HILDON_SIZE_FINGER_HEIGHT
|
395 HILDON_SIZE_AUTO_WIDTH
,
396 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL
,
397 "Disconnect", priv
->current
);
398 hildon_button_set_style (HILDON_BUTTON (button
),
399 HILDON_BUTTON_STYLE_PICKER
);
400 g_signal_connect (button
, "clicked", G_CALLBACK (disconnect_clicked
),
402 gtk_box_pack_start (GTK_BOX (hbox
), button
, TRUE
, TRUE
, 0);
403 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
407 button_clicked (HildonButton
*button
, StrongswanStatus
*plugin
)
409 StrongswanStatusPrivate
*priv
= plugin
->priv
;
411 priv
->dialog
= gtk_dialog_new ();
412 gtk_window_set_title (GTK_WINDOW (priv
->dialog
), "strongSwan VPN");
413 g_signal_connect (priv
->dialog
, "response",
414 G_CALLBACK (dialog_response
), plugin
);
416 switch (priv
->status
)
418 case STATUS_DISCONNECTED
:
419 setup_dialog_disconnected (plugin
);
421 case STATUS_CONNECTING
:
422 setup_dialog_disconnected (plugin
);
423 update_dialog_connecting (plugin
);
425 case STATUS_CONNECTED
:
426 setup_dialog_connected (plugin
);
430 gtk_widget_show_all (priv
->dialog
);
434 dbus_req_handler(const gchar
*interface
, const gchar
*method
,
435 GArray
*arguments
, StrongswanStatus
*plugin
,
438 if (!strcmp (method
, "StatusChanged") && arguments
->len
== 1)
441 osso_rpc_t
*arg
= &g_array_index(arguments
, osso_rpc_t
, 0);
442 if (arg
->type
== DBUS_TYPE_INT32
)
444 status
= arg
->value
.i
;
446 gchar
*msg
= g_strdup_printf ("Status changed to %d...", status
);
447 hildon_banner_show_information (NULL
, NULL
, msg
);
454 load_icon (GtkIconTheme
*theme
, const gchar
*name
, gint size
)
456 GdkPixbuf
*icon
= NULL
;
457 GdkPixbuf
*loaded
= gtk_icon_theme_load_icon (theme
, name
, size
,
458 GTK_ICON_LOOKUP_NO_SVG
, NULL
);
460 { /* so we don't have to listen for theme changes, we copy the icon */
461 icon
= gdk_pixbuf_copy (loaded
);
462 g_object_unref (loaded
);
468 load_icons (StrongswanStatusPrivate
*priv
)
470 GtkIconTheme
*theme
= gtk_icon_theme_get_default ();
471 priv
->icons
.status_open
= load_icon (theme
, "strongswan_lock_open",
473 priv
->icons
.status_close
= load_icon (theme
, "strongswan_lock_close",
475 priv
->icons
.button_open
= load_icon (theme
, "strongswan_lock_open",
477 priv
->icons
.button_close
= load_icon (theme
, "strongswan_lock_close",
479 if (!priv
->icons
.status_open
|| !priv
->icons
.button_open
)
481 hildon_banner_show_information (NULL
, NULL
, "failed to load icons");
486 strongswan_status_init (StrongswanStatus
*plugin
)
488 StrongswanStatusPrivate
*priv
= STRONGSWAN_STATUS_GET_PRIVATE (plugin
);
491 priv
->context
= osso_initialize (OSSO_STATUS_SERVICE
, "0.0.1", TRUE
, NULL
);
496 osso_return_t result
;
497 result
= osso_rpc_set_cb_f (priv
->context
,
501 (osso_rpc_cb_f
*)dbus_req_handler
,
503 if (result
!= OSSO_OK
)
508 priv
->conns
= strongswan_connections_new ();
512 hd_status_plugin_item_set_status_area_icon (HD_STATUS_PLUGIN_ITEM (plugin
),
513 priv
->icons
.status_open
);
515 GtkWidget
*button
= hildon_button_new_with_text (
516 HILDON_SIZE_FINGER_HEIGHT
| HILDON_SIZE_AUTO_WIDTH
,
517 HILDON_BUTTON_ARRANGEMENT_VERTICAL
,
518 "strongSwan VPN", "Not connected");
519 hildon_button_set_style (HILDON_BUTTON (button
),
520 HILDON_BUTTON_STYLE_PICKER
);
521 priv
->button
= button
;
522 gtk_container_add (GTK_CONTAINER (plugin
), button
);
524 GtkWidget
*image
= gtk_image_new_from_pixbuf (priv
->icons
.button_open
);
526 hildon_button_set_image (HILDON_BUTTON (button
), image
);
528 gtk_button_set_alignment (GTK_BUTTON (button
), 0.0, 0.5);
530 g_signal_connect (button
, "clicked", G_CALLBACK (button_clicked
), plugin
);
532 gtk_widget_show_all (GTK_WIDGET (plugin
));
536 strongswan_status_dispose (GObject
*object
)
538 StrongswanStatusPrivate
*priv
= STRONGSWAN_STATUS (object
)->priv
;
541 priv
->conns
= (g_object_unref (priv
->conns
), NULL
);
543 if (priv
->icons
.status_open
)
545 g_object_unref (priv
->icons
.status_open
);
546 priv
->icons
.status_open
= NULL
;
548 if (priv
->icons
.status_close
)
550 g_object_unref (priv
->icons
.status_close
);
551 priv
->icons
.status_close
= NULL
;
553 if (priv
->icons
.button_open
)
555 g_object_unref (priv
->icons
.button_open
);
556 priv
->icons
.button_open
= NULL
;
558 if (priv
->icons
.button_close
)
560 g_object_unref (priv
->icons
.button_close
);
561 priv
->icons
.button_close
= NULL
;
563 G_OBJECT_CLASS (strongswan_status_parent_class
)->dispose (object
);
567 strongswan_status_finalize (GObject
*object
)
569 StrongswanStatusPrivate
*priv
= STRONGSWAN_STATUS (object
)->priv
;
570 priv
->current
= (g_free (priv
->current
), NULL
);
571 G_OBJECT_CLASS (strongswan_status_parent_class
)->finalize (object
);
575 strongswan_status_class_finalize (StrongswanStatusClass
*klass
)
580 strongswan_status_class_init (StrongswanStatusClass
*klass
)
582 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
584 object_class
->dispose
= strongswan_status_dispose
;
585 object_class
->finalize
= strongswan_status_finalize
;
587 g_type_class_add_private (klass
, sizeof (StrongswanStatusPrivate
));