diff --git a/configure.ac b/configure.ac index 64e4fd5..00c1cd1 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ AC_PREREQ([2.59]) AC_INIT([gopenvpn], [0.8], [gopenvpn-users@lists.sourceforge.net]) AC_CONFIG_AUX_DIR([.]) AM_INIT_AUTOMAKE([foreign -Wall -Werror]) -AM_GNU_GETTEXT_VERSION([0.18.1]) +AM_GNU_GETTEXT_VERSION([0.18.3]) AM_GNU_GETTEXT([external]) AC_PROG_CC @@ -47,6 +47,17 @@ AC_CHECK_FUNCS([socket strrchr]) # Checks for needed packages (pkg-config) PKG_PROG_PKG_CONFIG +PKG_CHECK_MODULES(LIBSECRET, [libsecret-1 >= 0.15], + [AC_DEFINE([HAVE_LIBSECRET], [1], [Use libsecret])], + [PKG_CHECK_MODULES([GNOME_KEYRING], [gnome-keyring-1], + [AC_DEFINE([HAVE_GNOME_KEYRING], [1], [Use gnome-keyring]) + ]) +]) +AC_SUBST(LIBSECRET_CFLAGS) +AC_SUBST(LIBSECRET_LIBS) +AC_SUBST(GNOME_KEYRING_CFLAGS) +AC_SUBST(GNOME_KEYRING_LIBS) + PKG_CHECK_MODULES(GTK, gtk+-2.0) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) @@ -55,16 +66,23 @@ PKG_CHECK_MODULES(GLADE, libglade-2.0) AC_SUBST(GLADE_CFLAGS) AC_SUBST(GLADE_LIBS) -PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1) -AC_SUBST(GNOME_KEYRING_CFLAGS) -AC_SUBST(GNOME_KEYRING_LIBS) - PKG_CHECK_MODULES(X11, x11) AC_SUBST(X11_CFLAGS) AC_SUBST(X11_LIBS) PKG_CHECK_MODULES(POLKIT, polkit-gobject-1 >= 0.96) +# Check for AppIndicator +APPINDICATOR_LIBS= + +PKG_CHECK_MODULES(APPINDICATOR, appindicator-0.1, + [AC_DEFINE([USE_APPINDICATOR],[1],[Use AppIndicator1-0.1])], + [AC_MSG_WARN(AppIndicator 1-0.1 not present")]) + +AM_CONDITIONAL(APPINDICATOR, test -n "$APPINDICATOR_LIBS") +AC_SUBST(APPINDICATOR_CFLAGS) +AC_SUBST(APPINDICATOR_LIBS) + # Check for PolicyKit pkexec - can be overridden by --with-pkexec AC_ARG_WITH([pkexec], AC_HELP_STRING([--with-pkexec=/path/to/pkexec], [Full path to PolicyKit pkexec])) diff --git a/debian/control b/debian/control index 8cb749f..62b49d2 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,9 @@ Source: gopenvpn Section: net Priority: extra Maintainer: Sam Burney -Build-Depends: debhelper (>= 7), libglib2.0-dev, libgtk2.0-dev, libglade2-dev, libgnome-keyring-dev, build-essential, autogen, automake, autoconf, intltool, libpolkit-gobject-1-dev +Build-Depends: debhelper (>= 7), libglib2.0-dev, libgtk2.0-dev, libglade2-dev, + libsecret-1-dev | libgnome-keyring-dev, + build-essential, autogen, automake, autoconf, intltool, libpolkit-gobject-1-dev Standards-Version: 3.8.0 Homepage: http://gopenvpn.sourceforge.net/ diff --git a/debian/gopenvpn.substvars b/debian/gopenvpn.substvars index ac13204..0082b97 100644 --- a/debian/gopenvpn.substvars +++ b/debian/gopenvpn.substvars @@ -1,2 +1,3 @@ -shlibs:Depends=libatk1.0-0 (>= 1.29.3), libc6 (>= 2.3.6-6~), libc6 (>= 2.4), libcairo2 (>= 1.2.4), libfontconfig1 (>= 2.8.0), libfreetype6 (>= 2.2.1), libglade2-0 (>= 1:2.6.1), libglib2.0-0 (>= 2.23.5), libgnome-keyring0 (>= 2.20.3), libgtk2.0-0 (>= 2.10.0), libpango1.0-0 (>= 1.14.0), libx11-6 (>= 0), libxml2 (>= 2.6.27) +shlibs:Depends=libatk1.0-0 (>= 1.12.4), libc6 (>= 2.3.6-6~), libc6 (>= 2.27), libcairo2 (>= 1.2.4), libfontconfig1 (>= 2.12.6), libfreetype6 (>= 2.2.1), libgdk-pixbuf2.0-0 (>= 2.22.0), libglade2-0 (>= 1:2.6.4-2~), libglib2.0-0 (>= 2.24.0), libgtk2.0-0 (>= 2.10.0), libpango-1.0-0 (>= 1.14.0), libpangocairo-1.0-0 (>= 1.14.0), libpangoft2-1.0-0 (>= 1.14.0), libsecret-1-0 (>= 0.7), libx11-6, libxml2 (>= 2.6.27) misc:Depends= +misc:Pre-Depends= diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am index 58de846..135882a 100644 --- a/pixmaps/Makefile.am +++ b/pixmaps/Makefile.am @@ -2,5 +2,9 @@ pixmapsdir = $(datadir)/gopenvpn pixmaps_DATA = gopenvpn-open.png \ gopenvpn-connecting.png \ gopenvpn-blink.png \ - gopenvpn-closed.png + gopenvpn-closed.png \ + gopenvpn-active.svg \ + gopenvpn-inactive.svg \ + gopenvpn-processing.svg \ + gopenvpn-processing-2.svg EXTRA_DIST = $(pixmaps_DATA) diff --git a/pixmaps/gopenvpn-active.svg b/pixmaps/gopenvpn-active.svg new file mode 100644 index 0000000..21a9264 --- /dev/null +++ b/pixmaps/gopenvpn-active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/pixmaps/gopenvpn-inactive.svg b/pixmaps/gopenvpn-inactive.svg new file mode 100644 index 0000000..013bcfe --- /dev/null +++ b/pixmaps/gopenvpn-inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/pixmaps/gopenvpn-processing-2.svg b/pixmaps/gopenvpn-processing-2.svg new file mode 100644 index 0000000..8b7344a --- /dev/null +++ b/pixmaps/gopenvpn-processing-2.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/pixmaps/gopenvpn-processing.svg b/pixmaps/gopenvpn-processing.svg new file mode 100644 index 0000000..b5896cb --- /dev/null +++ b/pixmaps/gopenvpn-processing.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 598a564..2c2f026 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,14 +8,18 @@ endif gopenvpn_LDADD = $(GTK_LIBS) \ $(GLADE_LIBS) \ + $(LIBSECRET_LIBS) \ $(GNOME_KEYRING_LIBS) \ - $(X11_LIBS) + $(X11_LIBS) \ + $(APPINDICATOR_LIBS) AM_CFLAGS = -Wall -ansi -pedantic \ $(GLADE_CFLAGS) \ + $(LIBSECRET_CFLAGS) \ $(GNOME_KEYRING_CFLAGS) \ $(GTK_CFLAGS) \ $(X11_CFLAGS) \ + $(APPINDICATOR_CFLAGS) \ -DPIXMAPS_DIR=\""$(datadir)/gopenvpn"\" \ -DSYSCONF_DIR=\""$(sysconfdir)"\" \ -DLOCALSTATE_DIR=\""$(localstatedir)"\" \ diff --git a/src/gopenvpn.c b/src/gopenvpn.c index c01e746..8ed9eaf 100644 --- a/src/gopenvpn.c +++ b/src/gopenvpn.c @@ -47,7 +47,12 @@ #include #include #include +#ifdef HAVE_LIBSECRET +#include +#endif +#ifdef HAVE_GNOME_KEYRING #include +#endif #include "gettext.h" #include "gopenvpn.h" @@ -82,6 +87,10 @@ #include "eggtrayicon.h" #endif +#ifdef USE_APPINDICATOR +#include +#endif + /* * VPNConfig Section */ @@ -149,6 +158,11 @@ struct VPNApplet GHashTable *configs_table; gboolean batchmode; +#ifdef USE_APPINDICATOR + AppIndicator *app_indicator; + gboolean icon_blinking; + gboolean blink_on; +#endif #ifdef USE_GTKSTATUSICON GtkStatusIcon *status_icon; #else @@ -195,6 +209,82 @@ VPNApplet *g_applet = NULL; * GNOME keyring support */ +#ifdef HAVE_LIBSECRET + +/* schema */ +const SecretSchema * +gopenvpn_get_secret_schema (void) +{ + static const SecretSchema the_schema = { + "org.gnome.gopenvpn.Password", SECRET_SCHEMA_NONE, + { + { "config_name", SECRET_SCHEMA_ATTRIBUTE_STRING }, + { "NULL", 0 }, + } + }; + return &the_schema; +} + +gboolean get_keyring(const char *config_name, + char **username, + char **passphrase) +{ + GError *error = NULL; + char **fields; + + gchar *password = secret_password_lookup_sync (GOPENVPN_SECRET_SCHEMA, + NULL, &error, + "config_name", config_name, + NULL); + if (error != NULL) { + return FALSE; + } else if (password == NULL) { + return FALSE; + } else { + fields = g_strsplit(password, ":", 2); + secret_password_free(password); + + if (g_strv_length(fields) != 2) + { + g_strfreev(fields); + return FALSE; + } + + if (username) + *username = g_strdup(fields[0]); + *passphrase = g_strdup(fields[1]); + g_strfreev(fields); + return TRUE; + } +} + +void set_keyring(const char *config_name, + const char *username, + const char *passphrase) +{ + GError *error = NULL; + + + char *display_name; + char *secret; + + display_name = g_strdup_printf(_("Passphrase for OpenVPN connection %s"), config_name); + secret = g_strdup_printf("%s:%s", username ? username : "", passphrase); + + secret_password_store_sync (GOPENVPN_SECRET_SCHEMA, SECRET_COLLECTION_DEFAULT, + display_name, secret, NULL, &error, + "config_name", config_name, + NULL); + g_assert(error == NULL); + if (error != NULL) { + g_error_free (error); + } + g_free(display_name); + g_free(secret); +} +#endif + +#ifdef HAVE_GNOME_KEYRING gboolean get_keyring(const char *config_name, char **username, char **passphrase) @@ -267,6 +357,7 @@ void set_keyring(const char *config_name, gnome_keyring_attribute_list_free(attributes); g_free(display_name); } +#endif /* * Utility functions @@ -1008,6 +1099,11 @@ VPNApplet *vpn_applet_new() self->preferences = NULL; self->configs_table = NULL; self->batchmode = FALSE; + #ifdef USE_APPINDICATOR + self->app_indicator = NULL; + self->icon_blinking = FALSE; + self->blink_on = FALSE; + #endif #ifdef USE_GTKSTATUSICON self->status_icon = NULL; #else @@ -1142,6 +1238,22 @@ gboolean vpn_applet_blink_icon(gpointer user_data) } #endif +#ifdef USE_APPINDICATOR +gboolean app_indicator_blink_icon(gpointer user_data) +{ + VPNApplet *applet = (VPNApplet*)user_data; + + if (!applet->icon_blinking) + return FALSE; + + app_indicator_set_icon(applet->app_indicator, applet->blink_on ? CONNECTING_IMAGE_AI : BLINK_IMAGE_AI); + + applet->blink_on = !applet->blink_on; + + return TRUE; +} +#endif + gboolean vpn_applet_get_password(VPNApplet *applet, const char *name, char **username, @@ -1225,6 +1337,30 @@ gboolean vpn_applet_get_password(VPNApplet *applet, void vpn_applet_set_icon_state(VPNApplet *applet, int state) { + #ifdef USE_APPINDICATOR + switch (state) + { + case INACTIVE: + applet->icon_blinking = FALSE; + app_indicator_set_icon(applet->app_indicator, CLOSED_IMAGE_AI); + break; + case CONNECTING: + case RECONNECTING: + case SENTSTATE: + app_indicator_set_icon(applet->app_indicator, CONNECTING_IMAGE_AI); + if (!applet->icon_blinking) + { + applet->icon_blinking = TRUE; + applet->blink_on = FALSE; + g_timeout_add(500, app_indicator_blink_icon, applet); + } + break; + case CONNECTED: + applet->icon_blinking = FALSE; + app_indicator_set_icon(applet->app_indicator, OPEN_IMAGE_AI); + break; + } + #endif #ifdef USE_GTKSTATUSICON switch (state) { @@ -1575,6 +1711,11 @@ void vpn_applet_init_popup_menu(VPNApplet *applet) details_item); gtk_menu_shell_append(GTK_MENU_SHELL(applet->menu), quit_item); + + #ifdef USE_APPINDICATOR + app_indicator_set_menu(applet->app_indicator, GTK_MENU(applet->menu)); + gtk_widget_show_all(applet->menu); + #endif } void vpn_applet_init_configs(VPNApplet *applet) @@ -1664,6 +1805,12 @@ void vpn_applet_reconnect_to_mgmt(VPNApplet *applet) void vpn_applet_init_status_icon(VPNApplet *applet) { + #ifdef USE_APPINDICATOR + applet->app_indicator = app_indicator_new_with_path("gopenvpn-icon", "gopenvpn", APP_INDICATOR_CATEGORY_OTHER, PIXMAPS_DIR); + app_indicator_set_status(applet->app_indicator, APP_INDICATOR_STATUS_ACTIVE); + app_indicator_set_icon(applet->app_indicator, CLOSED_IMAGE_AI); + app_indicator_set_title(applet->app_indicator, "GOpenVPN"); + #endif #ifdef USE_GTKSTATUSICON applet->status_icon = gtk_status_icon_new_from_file(applet->closed_image); @@ -1711,6 +1858,11 @@ void vpn_applet_destroy(VPNApplet *applet) if (applet->batchmode) return; + #ifdef USE_APPINDICATOR + if (applet->app_indicator) { + app_indicator_set_status(applet->app_indicator, APP_INDICATOR_STATUS_PASSIVE); + } + #endif #ifdef USE_GTKSTATUSICON if (applet->status_icon) g_object_unref(applet->status_icon); diff --git a/src/gopenvpn.h b/src/gopenvpn.h index 68931ef..7c52291 100644 --- a/src/gopenvpn.h +++ b/src/gopenvpn.h @@ -25,8 +25,23 @@ #define OPEN_IMAGE "gopenvpn-open.png" +/* For AppIndicator */ +#define CLOSED_IMAGE_AI "gopenvpn-inactive" + +#define CONNECTING_IMAGE_AI "gopenvpn-processing" + +#define BLINK_IMAGE_AI "gopenvpn-processing-2" + +#define OPEN_IMAGE_AI "gopenvpn-active" + #define GLADE_FILE "gopenvpn.glade" #define CONFIG_PATH "/etc/openvpn" #define MAX_RETRY 10 + +#ifdef HAVE_LIBSECRET +const SecretSchema * gopenvpn_get_secret_schema (void) G_GNUC_CONST; + +#define GOPENVPN_SECRET_SCHEMA gopenvpn_get_secret_schema () +#endif