gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r16546 - in gnunet-gtk/src: . setup


From: gnunet
Subject: [GNUnet-SVN] r16546 - in gnunet-gtk/src: . setup
Date: Mon, 15 Aug 2011 16:15:47 +0200

Author: grothoff
Date: 2011-08-15 16:15:47 +0200 (Mon, 15 Aug 2011)
New Revision: 16546

Added:
   gnunet-gtk/src/setup/
   gnunet-gtk/src/setup/gnunet-setup-datacache-config.c
   gnunet-gtk/src/setup/gnunet-setup-datacache-plugins.c
   gnunet-gtk/src/setup/gnunet-setup-datastore-config.c
   gnunet-gtk/src/setup/gnunet-setup-datastore-plugins.c
   gnunet-gtk/src/setup/gnunet-setup-hostlist-editing.c
   gnunet-gtk/src/setup/gnunet-setup-options.c
   gnunet-gtk/src/setup/gnunet-setup-options.h
   gnunet-gtk/src/setup/gnunet-setup-transport-http.c
   gnunet-gtk/src/setup/gnunet-setup-transport-https.c
   gnunet-gtk/src/setup/gnunet-setup-transport-plugins.c
   gnunet-gtk/src/setup/gnunet-setup-transport-tcp.c
   gnunet-gtk/src/setup/gnunet-setup-transport-udp.c
   gnunet-gtk/src/setup/gnunet-setup-transport.c
   gnunet-gtk/src/setup/gnunet-setup.c
   gnunet-gtk/src/setup/gnunet-setup.h
Log:
importing gnunet-setup

Copied: gnunet-gtk/src/setup/gnunet-setup-datacache-config.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-datacache-config.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-datacache-config.c                        
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-datacache-config.c        2011-08-15 
14:15:47 UTC (rev 16546)
@@ -0,0 +1,137 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-datacache-config.c
+ * @brief test datacache configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_datacache_plugin.h>
+
+/**
+ * Stub implementation of the 'DeleteNotifyCallback' callback.
+ */
+static void
+dnc_dummy (void *cls, 
+          const GNUNET_HashCode *key,
+          size_t size)
+{
+  /* do nothing */
+}
+
+
+/**
+ * Test if the configuration works for the given plugin.
+ *
+ * @param name name of the plugin to check
+ * @return GNUNET_OK on success, GNUNET_SYSERR if the config is wrong
+ */
+static int
+test_config (const char *name)
+{
+  struct GNUNET_DATACACHE_PluginEnvironment env =
+    {
+      cfg,
+      "dhtcache", 
+      NULL, &dnc_dummy, 
+      1024LL
+    };
+  void *ret;
+
+  ret = GNUNET_PLUGIN_load (name, &env);
+  if (NULL == ret)
+    return GNUNET_SYSERR;
+  GNUNET_PLUGIN_unload (name, ret);
+  return GNUNET_OK;
+}
+
+
+static void
+show (const char *name)
+{
+  gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (builder, 
+                                                      name)));
+}
+
+
+static void
+hide (const char *name)
+{
+  gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, 
+                                                      name)));
+}
+
+
+void
+GNUNET_setup_datacache_mysql_invalidate_cb ()
+{
+  hide ("GNUNET_setup_datacache_mysql_tab_ok_image");
+  hide ("GNUNET_setup_datacache_mysql_tab_error_image");
+}
+
+
+void
+GNUNET_setup_datacache_postgres_invalidate_cb ()
+{
+  hide ("GNUNET_setup_datacache_postgres_tab_ok_image");
+  hide ("GNUNET_setup_datacache_postgres_tab_error_image");
+}
+
+
+void
+GNUNET_setup_datacache_mysql_tab_test_button_clicked_cb (GtkWidget *widget,
+                                                        gpointer user_data)
+{
+  if (GNUNET_OK == 
+      test_config ("libgnunet_plugin_datacache_mysql"))
+    {
+      show ("GNUNET_setup_datacache_mysql_tab_ok_image");
+      hide ("GNUNET_setup_datacache_mysql_tab_error_image");
+    }
+  else
+    {
+      hide ("GNUNET_setup_datacache_mysql_tab_ok_image");
+      show ("GNUNET_setup_datacache_mysql_tab_error_image");
+    }
+}
+
+
+void
+GNUNET_setup_datacache_postgres_tab_test_button_clicked_cb (GtkWidget *widget,
+                                                           gpointer user_data)
+{
+  if (GNUNET_OK == 
+      test_config ("libgnunet_plugin_datacache_postgres"))
+    {
+      show ("GNUNET_setup_datacache_postgres_tab_ok_image");
+      hide ("GNUNET_setup_datacache_postgres_tab_error_image");
+    }
+  else
+    {
+      hide ("GNUNET_setup_datacache_postgres_tab_ok_image");
+      show ("GNUNET_setup_datacache_postgres_tab_error_image");
+    }
+}
+
+
+
+/* end of gnunet-setup-datacache-config.c */
+

Copied: gnunet-gtk/src/setup/gnunet-setup-datacache-plugins.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-datacache-plugins.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-datacache-plugins.c                       
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-datacache-plugins.c       2011-08-15 
14:15:47 UTC (rev 16546)
@@ -0,0 +1,83 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-datacache-plugins.c
+ * @brief (de)sensitize transport plugin buttons based on plugin availability
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+
+
+/**
+ * Test if the given plugin exists and change the sensitivity
+ * of the widget accordingly.
+ *
+ * @param widget widget to update
+ * @param name name of the plugin to check
+ */
+static void
+test_plugin (GtkWidget *widget,
+            const char *name)
+{
+  if (GNUNET_YES ==
+      GNUNET_PLUGIN_test (name))
+    {
+      gtk_widget_set_sensitive (widget, 
+                               TRUE);
+    }
+  else
+    {
+      gtk_widget_set_sensitive (widget, 
+                               FALSE);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), 
+                                   FALSE);
+    }
+}
+
+
+
+void
+GNUNET_setup_fs_datacache_sqlite_radiobutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_datacache_sqlite");
+}
+
+
+void
+GNUNET_setup_fs_datacache_mysql_radiobutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_datacache_mysql");
+}
+
+
+void
+GNUNET_setup_fs_datacache_postgres_radiobutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_datacache_postgres");
+}
+
+
+
+/* end of gnunet-setup-transport-plugins.c */
+

Copied: gnunet-gtk/src/setup/gnunet-setup-datastore-config.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-datastore-config.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-datastore-config.c                        
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-datastore-config.c        2011-08-15 
14:15:47 UTC (rev 16546)
@@ -0,0 +1,133 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-datastore-config.c
+ * @brief test datastore configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_datastore_plugin.h>
+
+/**
+ * Stub implementation of the 'DiskUtilizationChange' callback.
+ */
+static void
+duc_dummy (void *cls, int delta)
+{
+  /* do nothing */
+}
+
+
+/**
+ * Test if the configuration works for the given plugin.
+ *
+ * @param name name of the plugin to check
+ * @return GNUNET_OK on success, GNUNET_SYSERR if the config is wrong
+ */
+static int
+test_config (const char *name)
+{
+  struct GNUNET_DATASTORE_PluginEnvironment env =
+    {
+      cfg,
+      &duc_dummy, NULL
+    };
+  void *ret;
+
+  ret = GNUNET_PLUGIN_load (name, &env);
+  if (NULL == ret)
+    return GNUNET_SYSERR;
+  GNUNET_PLUGIN_unload (name, ret);
+  return GNUNET_OK;
+}
+
+
+static void
+show (const char *name)
+{
+  gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (builder, 
+                                                      name)));
+}
+
+
+static void
+hide (const char *name)
+{
+  gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, 
+                                                      name)));
+}
+
+
+void
+GNUNET_setup_datastore_mysql_invalidate_cb ()
+{
+  hide ("GNUNET_setup_datastore_mysql_tab_ok_image");
+  hide ("GNUNET_setup_datastore_mysql_tab_error_image");
+}
+
+
+void
+GNUNET_setup_datastore_postgres_invalidate_cb ()
+{
+  hide ("GNUNET_setup_datastore_postgres_tab_ok_image");
+  hide ("GNUNET_setup_datastore_postgres_tab_error_image");
+}
+
+
+void
+GNUNET_setup_datastore_mysql_tab_test_button_clicked_cb (GtkWidget *widget,
+                                                        gpointer user_data)
+{
+  if (GNUNET_OK == 
+      test_config ("libgnunet_plugin_datastore_mysql"))
+    {
+      show ("GNUNET_setup_datastore_mysql_tab_ok_image");
+      hide ("GNUNET_setup_datastore_mysql_tab_error_image");
+    }
+  else
+    {
+      hide ("GNUNET_setup_datastore_mysql_tab_ok_image");
+      show ("GNUNET_setup_datastore_mysql_tab_error_image");
+    }
+}
+
+
+void
+GNUNET_setup_datastore_postgres_tab_test_button_clicked_cb (GtkWidget *widget,
+                                                           gpointer user_data)
+{
+  if (GNUNET_OK == 
+      test_config ("libgnunet_plugin_datastore_postgres"))
+    {
+      show ("GNUNET_setup_datastore_postgres_tab_ok_image");
+      hide ("GNUNET_setup_datastore_postgres_tab_error_image");
+    }
+  else
+    {
+      hide ("GNUNET_setup_datastore_postgres_tab_ok_image");
+      show ("GNUNET_setup_datastore_postgres_tab_error_image");
+    }
+}
+
+
+
+/* end of gnunet-setup-datastore-config.c */
+

Copied: gnunet-gtk/src/setup/gnunet-setup-datastore-plugins.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-datastore-plugins.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-datastore-plugins.c                       
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-datastore-plugins.c       2011-08-15 
14:15:47 UTC (rev 16546)
@@ -0,0 +1,81 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-datastore-plugins.c
+ * @brief (de)sensitize datastore plugin buttons based on plugin availability
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+
+/**
+ * Test if the given plugin exists and change the sensitivity
+ * of the widget accordingly.
+ *
+ * @param widget widget to update
+ * @param name name of the plugin to check
+ */
+static void
+test_plugin (GtkWidget *widget,
+            const char *name)
+{
+  if (GNUNET_YES ==
+      GNUNET_PLUGIN_test (name))
+    {
+      gtk_widget_set_sensitive (widget, 
+                               TRUE);
+    }
+  else
+    {
+      gtk_widget_set_sensitive (widget, 
+                               FALSE);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), 
+                                   FALSE);
+    }
+}
+
+
+void
+GNUNET_setup_fs_datastore_sqlite_radiobutton_realize_cb (GtkWidget *widget,
+                                                        gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_datastore_sqlite");
+}
+
+
+void
+GNUNET_setup_fs_datastore_mysql_radiobutton_realize_cb (GtkWidget *widget,
+                                                       gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_datastore_mysql");
+}
+
+
+void
+GNUNET_setup_fs_datastore_postgres_radiobutton_realize_cb (GtkWidget *widget,
+                                                          gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_datastore_postgres");
+}
+
+
+
+/* end of gnunet-setup-datastore-plugins.c */
+

Copied: gnunet-gtk/src/setup/gnunet-setup-hostlist-editing.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-hostlist-editing.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-hostlist-editing.c                        
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-hostlist-editing.c        2011-08-15 
14:15:47 UTC (rev 16546)
@@ -0,0 +1,72 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-hostlist-editing.c
+ * @brief allow editing of the hostlist
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+
+/**
+ * Handle editing of text in the GtkListModel.  Changes
+ * the new entry to non-editable and creates another
+ * empty entry at the end.
+ *
+ * @param renderer renderer emitting the signal
+ * @param path path identifying the edited cell
+ * @param new_text text that was added
+ * @param user_data not used
+ */
+void
+GNUNET_setup_hostlist_url_cellrenderertext_edited_cb (GtkCellRendererText 
*renderer,
+                                                     gchar *path,
+                                                     gchar *new_text,
+                                                     gpointer user_data)
+{
+  GtkListStore *ls;
+  GtkTreeIter old;
+  GtkTreeIter iter;
+
+  ls = GTK_LIST_STORE (gtk_builder_get_object (builder, 
+                                              
"GNUNET_setup_hostlist_url_liststore"));
+  if (ls == NULL)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (TRUE != 
+      gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ls),
+                                          &old,
+                                          path))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  
+  gtk_list_store_insert_before (ls, &iter, &old);
+  gtk_list_store_set (ls,
+                     &iter,
+                     0, new_text,
+                     1, FALSE,
+                     -1);
+}
+
+/* end of gnunet-setup-hostlist-editing.c */

Copied: gnunet-gtk/src/setup/gnunet-setup-options.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-options.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-options.c                         (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-options.c 2011-08-15 14:15:47 UTC (rev 
16546)
@@ -0,0 +1,2580 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-options.c
+ * @brief configuration details
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup-options.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gdk/gdkkeysyms.h>
+
+/**
+ * Regular expression for YES
+ */
+#define REX_YES "^YES$"
+
+/**
+ * Regular expression for NO
+ */
+#define REX_NO "^NO$"
+
+
+/**
+ * Initialize a toggle button based on an options 'yes/no' value.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_yes_no (const void *cls,
+            const char *section,
+            const char *option,
+            const char *value,
+            GObject *widget,
+            const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkToggleButton *button;
+
+  button = GTK_TOGGLE_BUTTON (widget);
+  if (button == NULL)
+    return GNUNET_SYSERR;
+  gtk_toggle_button_set_active (button,
+                               (0 == strcasecmp (value, "YES")) ? TRUE : 
FALSE);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Set a yes/no option based on a toggle button.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param widget widget to initialize
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+save_yes_no (const void *cls,
+            const char *section,
+            const char *option,
+            GObject *widget,
+            struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkToggleButton *button;                    
+  gboolean mode;
+
+  button = GTK_TOGGLE_BUTTON (widget);
+  if (button == NULL)
+    return GNUNET_SYSERR;
+  mode = gtk_toggle_button_get_active (button);
+  GNUNET_CONFIGURATION_set_value_string (cfg, 
+                                        section, option,
+                                        mode == TRUE ? "YES" : "NO");
+  return GNUNET_OK;
+}
+
+
+/**
+ * Initialize a GtkFileChooser based on a filename option.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_filename (const void *cls,
+              const char *section,
+              const char *option,
+              const char *value,
+              GObject *widget,
+              const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkFileChooser *chooser;
+
+  chooser = GTK_FILE_CHOOSER (widget);
+  if (chooser == NULL)
+    return GNUNET_SYSERR;
+  gtk_file_chooser_set_filename (chooser,
+                                value);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Set filename option based on a file chooser.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param widget widget to initialize
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+save_filename (const void *cls,
+              const char *section,
+              const char *option,
+              GObject *widget,
+              struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkFileChooser *chooser;
+  gchar *fn;
+
+  chooser = GTK_FILE_CHOOSER (widget);
+  if (chooser == NULL)
+    return GNUNET_SYSERR;
+  fn = gtk_file_chooser_get_filename (chooser);
+  if (fn == NULL)
+    fn = g_strdup ("");
+  GNUNET_CONFIGURATION_set_value_string (cfg, 
+                                        section, option,
+                                        fn);
+  g_free (fn);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Initialize a GtkEntry based on a text option.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_text (const void *cls,
+          const char *section,
+          const char *option,
+          const char *value,
+          GObject *widget,
+          const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkEntry *entry;
+
+  entry = GTK_ENTRY (widget);
+  if (entry == NULL)
+    return GNUNET_SYSERR;
+  gtk_entry_set_text (entry,
+                     value);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Set text option based on a GtkEntry.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param widget widget to initialize
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+save_text (const void *cls,
+          const char *section,
+          const char *option,
+          GObject *widget,
+          struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkEntry *entry;
+  const gchar *txt;
+
+  entry = GTK_ENTRY (widget);
+  if (entry == NULL)
+    return GNUNET_SYSERR;
+  txt = gtk_entry_get_text (entry);
+  GNUNET_CONFIGURATION_set_value_string (cfg, 
+                                        section, option,
+                                        txt);
+  return GNUNET_OK;
+}
+
+
+#if 0
+/**
+ * Initialize a GtkComboBox based on a text option.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_combo_text (const void *cls,
+                const char *section,
+                const char *option,
+                const char *value,
+                GObject *widget,
+                const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkComboBoxText *cb;
+
+  cb = GTK_COMBO_BOX_TEXT (widget);
+  if (NULL == cb)
+    return GNUNET_SYSERR;
+  gtk_combo_box_text_append_text (cb, value);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Set text option based on a GtkComboBox.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param widget widget to initialize
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+save_combo_text (const void *cls,
+                const char *section,
+                const char *option,
+                GObject *widget,
+                struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkComboBox *cb;
+  gchar *c;
+
+  cb = GTK_COMBO_BOX (widget);
+  if (NULL == cb)
+    return GNUNET_SYSERR;
+  c = gtk_combo_box_get_active_text (cb);
+  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, c);
+  g_free (c);
+  return GNUNET_OK;
+}
+#endif
+
+
+/**
+ * Initialize a GtkSpinButton based on a numeric option.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_number (const void *cls,
+            const char *section,
+            const char *option,
+            const char *value,
+            GObject *widget,
+            const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkSpinButton *spin;
+  unsigned int number;
+
+  spin = GTK_SPIN_BUTTON (widget);
+  if (spin == NULL)
+    return GNUNET_SYSERR;
+  if (1 != sscanf (value, "%u", &number))
+    return GNUNET_SYSERR;
+  gtk_spin_button_set_value (spin,
+                            number);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Set numeric option based on a spin button.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param widget widget to initialize
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+save_number (const void *cls,
+            const char *section,
+            const char *option,
+            GObject *widget,
+            struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkSpinButton *spin;
+
+  spin = GTK_SPIN_BUTTON (widget);
+  if (spin == NULL)
+    return GNUNET_SYSERR;
+  GNUNET_CONFIGURATION_set_value_number (cfg, 
+                                        section, option,
+                                        gtk_spin_button_get_value_as_int 
(spin));
+  return GNUNET_OK;
+}
+
+
+/**
+ * Initialize a toggle button based on the existence of a word
+ * in an option value.
+ *
+ * @param cls word to test for (conat char *)
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_option_list (const void *cls,
+                 const char *section,
+                 const char *option,
+                 const char *value,
+                 GObject *widget,
+                 const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  const char *word = cls;
+  char *t;
+  char *w;
+  GtkToggleButton *button;
+  int found;
+
+  button = GTK_TOGGLE_BUTTON (widget);
+  if (button == NULL)
+    return GNUNET_SYSERR;
+  found = GNUNET_NO;
+  t = GNUNET_strdup (value);
+  w = strtok (t, " ");
+  while (w != NULL)
+    {
+      if (0 == strcmp (w, word))
+       {
+         found = GNUNET_YES;
+         break;
+       }
+      w = strtok (NULL, " ");
+    }
+  GNUNET_free (t);
+  gtk_toggle_button_set_active (button,
+                               found);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Add or remove a word from a sentence based on a toggle button's yes/no 
value.
+ *
+ * @param cls  word to add or remove for (conat char *)
+ * @param section section with the value
+ * @param option option name
+ * @param widget widget to initialize
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+save_option_list (const void *cls,
+                 const char *section,
+                 const char *option,
+                 GObject *widget,
+                 struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  const char *word = cls;
+  GtkToggleButton *button;
+  gboolean mode;
+
+  button = GTK_TOGGLE_BUTTON (widget);
+  if (button == NULL)
+    return GNUNET_SYSERR;
+  mode = gtk_toggle_button_get_active (button);
+  if (mode == TRUE)
+    GNUNET_CONFIGURATION_append_value_filename (cfg,
+                                               section,
+                                               option,
+                                               word);
+  else
+    GNUNET_CONFIGURATION_remove_value_filename (cfg,
+                                               section,
+                                               option,
+                                               word);
+  return GNUNET_OK;
+}
+
+
+/**
+ * User pressed a key in a sensitive tree view with a list store.
+ * Check if it was the 'delete' key and if so remove the selected
+ * row.
+ *
+ * @param tv tree view emitting the signal
+ * @param event key stroke data
+ * @param user_data not used
+ * @return TRUE to stop other handlers from being invoked
+ */
+gboolean
+GNUNET_setup_treeview_key_press_event_cb (GtkTreeView *tv,
+                                         GdkEventKey *event,
+                                         gpointer user_data)
+{
+  GtkListStore *ls;
+  GtkTreeModel *tm;
+  GtkTreeSelection *sel;
+  GtkTreeIter iter;
+  gboolean editable;
+
+  if ( (event->type != GDK_KEY_PRESS) ||
+       (event->state != 0) ||
+       (event->keyval != GDK_Delete) )
+    return FALSE;
+  ls = GTK_LIST_STORE (gtk_tree_view_get_model (tv));
+  if (ls == NULL)
+    {
+      GNUNET_break (0);
+      return FALSE;
+    }
+  sel = gtk_tree_view_get_selection (tv);
+  if (TRUE != 
+      gtk_tree_selection_get_selected (sel,
+                                      &tm,
+                                      &iter))    
+    return FALSE;
+  gtk_tree_model_get (tm, &iter, 1, &editable, -1);
+  if (TRUE == editable)
+    return FALSE; /* likely currently editing... */
+  gtk_list_store_remove (ls, &iter);
+  gtk_tree_model_get_iter_first (tm, &iter);
+  gtk_tree_selection_select_iter (sel, &iter);
+  return FALSE;
+}
+
+
+/**
+ * Initialize a GtkListStore by tokenizing the value into strings.
+ *
+ * @param cls closure (unused)
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_string_list_store (const void *cls,
+                       const char *section,
+                       const char *option,
+                       const char *value,
+                       GObject *widget,
+                       const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *t;
+  char *w;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+
+  ls = GTK_LIST_STORE (widget);
+  if (ls == NULL)
+    return GNUNET_SYSERR;
+  t = GNUNET_strdup (value);
+  w = strtok (t, " ");
+  while (w != NULL)
+    {
+      gtk_list_store_insert_with_values (ls,
+                                        &iter,
+                                        G_MAXINT, 
+                                        0, w,
+                                        1, FALSE,
+                                        -1);
+      w = strtok (NULL, " ");
+    }
+  GNUNET_free (t);
+  gtk_list_store_insert_with_values (ls,
+                                    &iter,
+                                    G_MAXINT, 
+                                    0, "",
+                                    1, TRUE,
+                                    -1);
+  return GNUNET_OK;
+}
+
+
+/**
+ * The GtkCellRenderer has emmited the 'edited' signal.
+ * 
+ *
+ * @param cls closure (unused)
+ * @param section section with the value (NULL)
+ * @param option option name (NULL)
+ * @param widget the cell renderer
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+save_string_list_store (const void *cls,
+                       const char *section,
+                       const char *option,
+                       GObject *widget,
+                       struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkTreeModel *tm;
+  GtkTreeIter iter;
+  char *value;
+  char *n;
+  gchar *val;
+
+  tm = GTK_TREE_MODEL (widget);
+  if (tm == NULL)
+    return GNUNET_SYSERR;
+  value = NULL;
+  if (TRUE == gtk_tree_model_get_iter_first (tm, &iter))
+    {
+      do
+       {
+         gtk_tree_model_get (tm,
+                             &iter,
+                             0, &val,
+                             -1);
+         if (value == NULL)
+           {
+             value = GNUNET_strdup (val);
+           }
+         else
+           {
+             GNUNET_asprintf (&n,
+                              "%s %s",                        
+                              value,
+                              val);
+             GNUNET_free (value);
+             value = n;
+           }
+         g_free (val);
+       }
+      while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+    }
+  if (value == NULL)
+    value = GNUNET_strdup ("");
+  GNUNET_CONFIGURATION_set_value_string (cfg,
+                                        section,
+                                        option,
+                                        value);
+  GNUNET_free (value);  
+  return GNUNET_OK;
+}
+
+
+/**
+ * Check if the section represents a DNS entry and then update the
+ * GtkListStore accordingly.
+ *
+ * @param cls the list store to modify
+ * @param section name of the section
+ */
+static void
+add_dns_entry_to_list_store (void *cls, const char *section)
+{
+  GtkListStore *ls = cls;
+  GtkTreeIter iter;
+  char *sld;
+  char *hostname;
+  char *hostport;
+  char *redirect;
+  char *cpy;
+  gboolean udp;
+  
+  if (NULL == section)
+    {
+      gtk_list_store_insert_with_values (ls,
+                                        &iter,
+                                        G_MAXINT,
+                                        0, "",
+                                        1, (guint) 80,
+                                        2, (guint) 8080,
+                                        3, "localhost",
+                                        4, "tcp",
+                                        -1);
+      return;
+    }
+
+  if ( (8 > strlen (section)) ||
+       (0 != strcmp (".gnunet.", section + ((strlen (section) - 8)))) )
+    return;
+  sld = GNUNET_strdup (section);
+  sld[strlen (section) - 8] = '\0';
+  udp = FALSE;
+  do
+    {
+      if (GNUNET_OK ==
+         GNUNET_CONFIGURATION_get_value_string (cfg, section,
+                                                (TRUE == udp) 
+                                                ? "UDP_REDIRECTS"
+                                                : "TCP_REDIRECTS",
+                                                &cpy))
+       {
+         for (redirect = strtok (cpy, " "); redirect != NULL;
+              redirect = strtok (NULL, " "))
+           {
+             if (NULL == (hostname = strstr (redirect, ":")))
+               {
+                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                             _("Option `%s' is not formatted correctly!\n"),
+                             redirect);
+                 continue;
+               }
+             hostname[0] = '\0';
+             hostname++;
+             if (NULL == (hostport = strstr (hostname, ":")))
+               {
+                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                             _("Option `%s' is not formatted correctly!\n"),
+                             redirect);
+                 continue;
+               }
+             hostport[0] = '\0';
+             hostport++;
+             
+             int local_port = atoi (redirect);
+             if (!((local_port > 0) && (local_port < 65536)))
+               {
+                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                             _("`%s' is not a valid port number!\n"), 
+                             redirect);          
+                 continue;
+               }
+             int host_port = atoi (hostport);
+             if (!((host_port > 0) && (host_port < 65536)))
+               {
+                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                             _("`%s' is not a valid port number!\n"), 
+                             hostport);          
+                 continue;
+               }
+             gtk_list_store_insert_with_values (ls,
+                                                &iter,
+                                                0,
+                                                0, sld,
+                                                1, (guint) local_port,
+                                                2, (guint) host_port,
+                                                3, hostname,
+                                                4, (TRUE == udp) ? "udp" : 
"tcp",
+                                                -1);
+           }
+         GNUNET_free (cpy);
+       }
+      udp = !udp;
+    }
+  while (udp != FALSE);
+  GNUNET_free (sld);
+}
+
+
+/**
+ * Initialize the GtkListModel with the VPN's DNS service specification.
+ *
+ * @param cls NULL
+ * @param section section with the value (NULL)
+ * @param option option name (NULL)
+ * @param value value as a string (NULL)
+ * @param widget widget to initialize (the GtkTreeView)
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+load_vpn_dns_configuration (const void *cls,
+                           const char *section,
+                           const char *option,
+                           const char *value,
+                           GObject *widget,
+                           const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GtkTreeView *tv;
+  GtkListStore *ls;
+
+  tv = GTK_TREE_VIEW (widget);
+  if (tv == NULL)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+  ls = GTK_LIST_STORE (gtk_tree_view_get_model (tv));
+  GNUNET_CONFIGURATION_iterate_sections (cfg,
+                                        &add_dns_entry_to_list_store,
+                                        ls);
+  /* finally, add empty entry */
+  add_dns_entry_to_list_store (ls, NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Records we use to build DNS information lists.
+ */
+struct DnsInfo 
+{
+  struct DnsInfo *next;
+  char *section;
+  char *altnames;
+  char *tcpred;
+  char *udpred;
+  unsigned long long ttl;  
+};
+
+
+/**
+ * Function called for each section in the configuration.
+ * Gather existing ttl, section names and altnames.
+ * 
+ * @param cls 'struct DnsInfo**' to create
+ * @param section name of a section in the configuration
+ */
+static void
+collect_dns_sections (void *cls,
+                     const char *section)
+{
+  struct DnsInfo **base = cls;
+  struct DnsInfo *pos;
+
+  if ( (8 > strlen (section)) ||
+       (0 != strcmp (".gnunet.", section + ((strlen (section) - 8)))) )
+    return;
+  pos = GNUNET_malloc (sizeof (struct DnsInfo));
+  pos->section = GNUNET_strdup (section);
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, section, "TTL", &pos->ttl))
+    pos->ttl = 3600000;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, section, 
"ALTERNATIVE_NAMES", &pos->altnames))
+    pos->altnames = NULL;
+  pos->tcpred = GNUNET_strdup ("");
+  pos->udpred = GNUNET_strdup ("");
+  pos->next = *base;
+  *base = pos;
+}
+
+
+/**
+ * Function called for each section in the configuration.
+ * Removes those ending in '.gnunet.'.
+ * 
+ * @param cls unused
+ * @param section name of a section in the configuration
+ */
+static void
+remove_dns_sections (void *cls,
+                    const char *section)
+{
+  if ( (8 > strlen (section)) ||
+       (0 != strcmp (".gnunet.", section + ((strlen (section) - 8)))) )
+    return;
+  GNUNET_CONFIGURATION_remove_section (cfg, section);
+}
+
+
+/**
+ * Given the list store and the data in it, update the 
+ * configuration file accordingly.
+ *
+ * @param tm model to use
+ */
+static void
+update_vpn_dns_configuration (GtkTreeModel *tm)
+{
+  GtkTreeIter iter;
+  gchar *hostname;
+  guint srcport;
+  guint targetport;
+  gchar *targethost;
+  gchar *tcpudp;
+  char *tmp;
+  struct DnsInfo *head;
+  struct DnsInfo *pos;
+
+  head = NULL;
+  GNUNET_CONFIGURATION_iterate_sections (cfg,
+                                        &collect_dns_sections,
+                                        &head);
+  if (TRUE ==
+      gtk_tree_model_get_iter_first (tm, &iter))
+    do
+      {  
+       gtk_tree_model_get (tm, &iter,
+                           0, &hostname,
+                           1, &srcport,
+                           2, &targetport,
+                           3, &targethost,
+                           4, &tcpudp,
+                           -1);
+       if (0 != strlen (hostname))
+         {
+           pos = head;
+           GNUNET_asprintf (&tmp,
+                            "%s.gnunet.",
+                            hostname);
+           while ( (NULL != pos) &&
+                   (0 != strcasecmp (tmp, pos->section)) )
+             pos = pos->next;
+           if (pos == NULL)
+             {
+               pos = GNUNET_malloc (sizeof (struct DnsInfo));
+               pos->section = tmp;
+               pos->ttl = 3600000;
+               pos->altnames = NULL;
+               pos->tcpred = GNUNET_strdup ("");
+               pos->udpred = GNUNET_strdup ("");
+               pos->next = head;
+               head = pos;
+             }
+           else
+             {
+               GNUNET_free (tmp);
+             }
+           
+           GNUNET_asprintf (&tmp,
+                            "%u:%s:%u %s",
+                            srcport,
+                            targethost,
+                            targetport,
+                            (0 == strcasecmp ("tcp", tcpudp)) ? pos->tcpred : 
pos->udpred);
+           if (0 == strcasecmp ("tcp", tcpudp))
+             {
+               GNUNET_free (pos->tcpred);
+               pos->tcpred = tmp;
+             }
+           else
+             {
+               GNUNET_free (pos->udpred);
+               pos->udpred = tmp;
+             }
+         }
+       g_free (tcpudp);
+       g_free (hostname);
+       g_free (targethost);
+      }
+    while (TRUE == gtk_tree_model_iter_next (tm, &iter));
+  GNUNET_CONFIGURATION_iterate_sections (cfg,
+                                        &remove_dns_sections,
+                                        NULL);
+  while (NULL != head)
+    {
+      pos = head;
+      head = pos->next;
+      if (pos->altnames != NULL)
+       GNUNET_CONFIGURATION_set_value_string (cfg,
+                                              pos->section,
+                                              "ALTERNATIVE_NAMES",
+                                              pos->altnames);
+      if (strlen (pos->udpred) > 0)
+       GNUNET_CONFIGURATION_set_value_string (cfg,
+                                              pos->section,
+                                              "UDP_REDIRECTS",
+                                              pos->udpred);
+      if (strlen (pos->tcpred) > 0)
+       GNUNET_CONFIGURATION_set_value_string (cfg,
+                                              pos->section,
+                                              "TCP_REDIRECTS",
+                                              pos->tcpred);
+      GNUNET_CONFIGURATION_set_value_number (cfg,
+                                            pos->section,
+                                            "TTL",
+                                            pos->ttl);
+      GNUNET_free_non_null (pos->altnames);
+      GNUNET_free (pos->tcpred);
+      GNUNET_free (pos->udpred);
+      GNUNET_free (pos->section);
+      GNUNET_free (pos);
+    }
+}
+
+
+/**
+ * The user has edited the DNS name of a service we're offering.
+ * Update the GtkTreeModel (at the given path) and update the
+ * respective service entry in the configuration file.  Finally,
+ * if the edited path is for a "fresh" entry, create another empty
+ * one at the bottom.  If the hostname was set to empty, remove
+ * the entire entry from the configuration and the model.
+ *
+ * @param renderer GtkCellRendererText that changed
+ * @param path GtkTreePath identifying where in the Model the change is
+ * @param new_text the new text that was stored in the line
+ * @param user_data NULL
+ */
+static void
+save_vpn_dns_service_dnsname (GtkCellRendererText *renderer,
+                             gchar *path,
+                             gchar *new_text,
+                             gpointer user_data) 
+{
+  GtkTreeModel *tm;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+  gchar *old;
+
+  tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, 
+                                              "vpn_dns_config_liststore"));
+  if (NULL == tm)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  ls = GTK_LIST_STORE (tm);
+  if (NULL == ls)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  gtk_tree_model_get (tm, &iter,
+                     0, &old,
+                     -1);
+  if ( (0 != strlen (old)) &&
+       (0 == strlen (new_text)) )
+    {
+      /* deletion */
+      gtk_list_store_remove (ls, &iter);
+      g_free (old);
+      return;
+    }
+  /* update model */
+  gtk_list_store_set (ls, &iter,
+                     0, new_text,
+                     -1);
+  /* update configuration */
+  update_vpn_dns_configuration (tm);
+  if ( (0 == strlen (old)) &&
+       (0 != strlen (new_text)) )
+    {
+      /* need another empty entry at the end for future expansion */
+      add_dns_entry_to_list_store (GTK_LIST_STORE (tm), NULL);
+    }                
+  g_free (old);
+}
+
+
+/**
+ * Initialize the GtkListModel with the VPN's DNS service specification.
+ *
+ * @param cls NULL
+ * @param section section with the value (NULL)
+ * @param option option name (NULL)
+ * @param widget widget to initialize (the GtkTreeView)
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+vpn_dns_service_dnsname_install_edited_handler (const void *cls,
+                                               const char *section,
+                                               const char *option,
+                                               GObject *widget,
+                                               struct 
GNUNET_CONFIGURATION_Handle *cfg)
+{
+  static int once;
+  GtkCellRendererText *rt;
+
+  rt = GTK_CELL_RENDERER_TEXT(widget);
+  if (NULL == rt)
+    return GNUNET_SYSERR;
+  if (0 != once++)
+    return GNUNET_OK;
+  g_signal_connect (rt,
+                   "edited",
+                   G_CALLBACK (&save_vpn_dns_service_dnsname),
+                   NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * The user has edited the DNS name of a service we're offering.
+ * Update the GtkTreeModel (at the given path) and update the
+ * respective service entry in the configuration file.  Finally,
+ * if the edited path is for a "fresh" entry, create another empty
+ * one at the bottom.  If the hostname was set to empty, remove
+ * the entire entry from the configuration and the model.
+ *
+ * @param renderer GtkCellRendererText that changed
+ * @param path GtkTreePath identifying where in the Model the change is
+ * @param new_text the new text that was stored in the line
+ * @param user_data NULL
+ */
+static void
+save_vpn_dns_service_tcpudp (GtkCellRendererText *renderer,
+                            gchar *path,
+                            gchar *new_text,
+                            gpointer user_data) 
+{
+  GtkTreeModel *tm;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+
+  if ( (0 != strcasecmp ("tcp", new_text)) &&
+       (0 != strcasecmp ("udp", new_text)) )
+    {
+      /* FIXME: warn... */
+      return;
+    }
+  tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, 
+                                              "vpn_dns_config_liststore"));
+  if (NULL == tm)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  ls = GTK_LIST_STORE (tm);
+  if (NULL == ls)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  /* update model */
+  gtk_list_store_set (ls, &iter,
+                     4, new_text,
+                     -1);
+  /* update configuration */
+  update_vpn_dns_configuration (tm);
+}
+
+
+/**
+ * Initialize the GtkListModel with the VPN's DNS service specification.
+ *
+ * @param cls NULL
+ * @param section section with the value (NULL)
+ * @param option option name (NULL)
+ * @param widget widget to initialize (the GtkTreeView)
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+vpn_dns_service_tcpudp_install_edited_handler (const void *cls,
+                                              const char *section,
+                                              const char *option,
+                                              GObject *widget,
+                                              struct 
GNUNET_CONFIGURATION_Handle *cfg)
+{
+  static int once;
+  GtkCellRendererText *rt;
+
+  rt = GTK_CELL_RENDERER_TEXT(widget);
+  if (NULL == rt)
+    return GNUNET_SYSERR;
+  if (0 != once++)
+    return GNUNET_OK;
+  g_signal_connect (rt,
+                   "edited",
+                   G_CALLBACK (&save_vpn_dns_service_tcpudp),
+                   NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * The user has edited the DNS name of a service we're offering.
+ * Update the GtkTreeModel (at the given path) and update the
+ * respective service entry in the configuration file.  Finally,
+ * if the edited path is for a "fresh" entry, create another empty
+ * one at the bottom.  If the hostname was set to empty, remove
+ * the entire entry from the configuration and the model.
+ *
+ * @param renderer GtkCellRendererText that changed
+ * @param path GtkTreePath identifying where in the Model the change is
+ * @param new_text the new text that was stored in the line
+ * @param user_data NULL
+ */
+static void
+save_vpn_dns_service_sourceport (GtkCellRendererText *renderer,
+                                gchar *path,
+                                gchar *new_text,
+                                gpointer user_data) 
+{
+  GtkTreeModel *tm;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+  int port;
+
+  port = atoi (new_text);
+  if ( (port < 1) || (port > UINT16_MAX) )
+    {
+      /* invalid port, FIXME: warn */
+      return;
+    }
+  tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, 
+                                              "vpn_dns_config_liststore"));
+  if (NULL == tm)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  ls = GTK_LIST_STORE (tm);
+  if (NULL == ls)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  /* update model */
+  gtk_list_store_set (ls, &iter,
+                     1, (guint) port,
+                     -1);
+  /* update configuration */
+  update_vpn_dns_configuration (tm);
+}
+
+
+/**
+ * Initialize the GtkListModel with the VPN's DNS service specification.
+ *
+ * @param cls NULL
+ * @param section section with the value (NULL)
+ * @param option option name (NULL)
+ * @param widget widget to initialize (the GtkTreeView)
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+vpn_dns_service_sourceport_install_edited_handler (const void *cls,
+                                                  const char *section,
+                                                  const char *option,
+                                                  GObject *widget,
+                                                  struct 
GNUNET_CONFIGURATION_Handle *cfg)
+{
+  static int once;
+  GtkCellRendererText *rt;
+
+  rt = GTK_CELL_RENDERER_TEXT(widget);
+  if (NULL == rt)
+    return GNUNET_SYSERR;
+  if (0 != once++)
+    return GNUNET_OK;
+  g_signal_connect (rt,
+                   "edited",
+                   G_CALLBACK (&save_vpn_dns_service_sourceport),
+                   NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * The user has edited the DNS name of a service we're offering.
+ * Update the GtkTreeModel (at the given path) and update the
+ * respective service entry in the configuration file.  Finally,
+ * if the edited path is for a "fresh" entry, create another empty
+ * one at the bottom.  If the hostname was set to empty, remove
+ * the entire entry from the configuration and the model.
+ *
+ * @param renderer GtkCellRendererText that changed
+ * @param path GtkTreePath identifying where in the Model the change is
+ * @param new_text the new text that was stored in the line
+ * @param user_data NULL
+ */
+static void
+save_vpn_dns_service_targethostname (GtkCellRendererText *renderer,
+                                    gchar *path,
+                                    gchar *new_text,
+                                    gpointer user_data) 
+{
+  GtkTreeModel *tm;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+
+  tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, 
+                                              "vpn_dns_config_liststore"));
+  if (NULL == tm)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  ls = GTK_LIST_STORE (tm);
+  if (NULL == ls)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  /* update model */
+  gtk_list_store_set (ls, &iter,
+                     3, new_text,
+                     -1);
+  /* update configuration */
+  update_vpn_dns_configuration (tm);
+}
+
+
+/**
+ * Initialize the GtkListModel with the VPN's DNS service specification.
+ *
+ * @param cls NULL
+ * @param section section with the value (NULL)
+ * @param option option name (NULL)
+ * @param widget widget to initialize (the GtkTreeView)
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+vpn_dns_service_targethostname_install_edited_handler (const void *cls,
+                                                      const char *section,
+                                                      const char *option,
+                                                      GObject *widget,
+                                                      struct 
GNUNET_CONFIGURATION_Handle *cfg)
+{
+  static int once;
+  GtkCellRendererText *rt;
+
+  rt = GTK_CELL_RENDERER_TEXT(widget);
+  if (NULL == rt)
+    return GNUNET_SYSERR;
+  if (0 != once++)
+    return GNUNET_OK;
+  g_signal_connect (rt,
+                   "edited",
+                   G_CALLBACK (&save_vpn_dns_service_targethostname),
+                   NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * The user has edited the DNS name of a service we're offering.
+ * Update the GtkTreeModel (at the given path) and update the
+ * respective service entry in the configuration file.  Finally,
+ * if the edited path is for a "fresh" entry, create another empty
+ * one at the bottom.  If the hostname was set to empty, remove
+ * the entire entry from the configuration and the model.
+ *
+ * @param renderer GtkCellRendererText that changed
+ * @param path GtkTreePath identifying where in the Model the change is
+ * @param new_text the new text that was stored in the line
+ * @param user_data NULL
+ */
+static void
+save_vpn_dns_service_targetport (GtkCellRendererText *renderer,
+                                gchar *path,
+                                gchar *new_text,
+                                gpointer user_data) 
+{
+  GtkTreeModel *tm;
+  GtkListStore *ls;
+  GtkTreeIter iter;
+  int port;
+
+  port = atoi (new_text);
+  if ( (port < 1) || (port > UINT16_MAX) )
+    {
+      /* invalid port, FIXME: warn */
+      return;
+    }
+  tm = GTK_TREE_MODEL (gtk_builder_get_object (builder, 
+                                              "vpn_dns_config_liststore"));
+  if (NULL == tm)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  ls = GTK_LIST_STORE (tm);
+  if (NULL == ls)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  /* update model */
+  gtk_list_store_set (ls, &iter,
+                     2, (guint) port,
+                     -1);
+  /* update configuration */
+  update_vpn_dns_configuration (tm);
+}
+
+
+/**
+ * Initialize the GtkListModel with the VPN's DNS service specification.
+ *
+ * @param cls NULL
+ * @param section section with the value (NULL)
+ * @param option option name (NULL)
+ * @param widget widget to initialize (the GtkTreeView)
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+static int
+vpn_dns_service_targetport_install_edited_handler (const void *cls,
+                                                  const char *section,
+                                                  const char *option,
+                                                  GObject *widget,
+                                                  struct 
GNUNET_CONFIGURATION_Handle *cfg)
+{
+  static int once;
+  GtkCellRendererText *rt;
+
+  rt = GTK_CELL_RENDERER_TEXT(widget);
+  if (NULL == rt)
+    return GNUNET_SYSERR;
+  if (0 != once++)
+    return GNUNET_OK;
+  g_signal_connect (rt,
+                   "edited",
+                   G_CALLBACK (&save_vpn_dns_service_targetport),
+                   NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Hide "min connected friends" option if in F2F-only mode.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification 
hide_min_connected_friends[] =
+{
+  { "GNUNET_setup_minimum_friends_label", NULL, REX_YES },
+  { "GNUNET_setup_minimum_friends_spinbutton", NULL, REX_YES },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "hostlist" options if hostlist is not in use.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_hostlist_options[] =
+{
+  { "GNUNET_setup_hostlist_client_enable_checkbutton", "(^| )hostlist($| )", 
NULL },
+  { "GNUNET_setup_hostlist_client_learn_checkbutton",  "(^| )hostlist($| )", 
NULL },
+  { "GNUNET_setup_hostlist_options_hbox",  "(^| )hostlist($| )", NULL },
+  { "GNUNET_setup_hostlist_frame",  "(^| )hostlist($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "exit" options if VPN exit is not in use.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_exit_options[] =
+{
+  { "GNUNET_setup_vpn_exit_frame", "(^| )exit($| )", NULL },
+  { "GNUNET_setup_vpn_service_configuration_frame", "(^| )exit($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "hostlist" server options if hostlist server is not in use.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification 
hide_hostlist_server_options[] =
+{
+  { "GNUNET_setup_hostlist_advertise_checkbutton",  "(^| )-p($| )", NULL },
+  { "GNUNET_setup_hostlist_port_label",  "(^| )-p($| )", NULL },
+  { "GNUNET_setup_hostlist_server_port_spin_button", "(^| )-p($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+
+/**
+ * Hide "fs tab" if FS not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_fs_tab[] =
+{
+  { "GNUNET_setup_fs_main_vbox", "(^| )fs($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+
+/**
+ * Hide "vpn tab" if VPN not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_vpn_tab[] =
+{
+  { "GNUNET_setup_vpn_vbox", "(^| )vpn($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+
+/**
+ * Hide "tcp tab" if TCP not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_tcp_tab[] =
+{
+  { "GNUNET_setup_transport_tcp_vbox", "(^| )tcp($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "udp tab" if UDP not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_udp_tab[] =
+{
+  { "GNUNET_setup_transport_udp_vbox", "(^| )udp($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "http tab" if HTTP not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_http_tab[] =
+{
+  { "GNUNET_setup_transport_http_vbox", "(^| )http($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "https tab" if HTTPS not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_https_tab[] =
+{
+  { "GNUNET_setup_transport_https_vbox", "(^| )https($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "dv tab" if DV not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_dv_tab[] =
+{
+  { "GNUNET_setup_transport_dv_vbox", "(^| )dv($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "wlan tab" if WLAN not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_wlan_tab[] =
+{
+  { "GNUNET_setup_transport_wlan_vbox", "(^| )wlan($| )", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "sqlite datastore" tab if sqlite not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_sqlite_datastore_tab[] 
=
+{
+  { "GNUNET_setup_fs_datastore_sqlite_label", "^sqlite$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "mysql datastore" tab if mysql not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_mysql_datastore_tab[] =
+{
+  { "GNUNET_setup_datastore_mysql_vbox", "^mysql$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "postgres datastore" tab if postgres not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification 
hide_postgres_datastore_tab[] =
+{
+  { "GNUNET_setup_datastore_postgres_hbox", "^postgres$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "sqlite datacache" tab if sqlite not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_sqlite_datacache_tab[] 
=
+{
+  { "GNUNET_setup_fs_datacache_sqlite_label", "^sqlite$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "mysql datacache" tab if mysql not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_mysql_datacache_tab[] =
+{
+  { "GNUNET_setup_datacache_mysql_vbox", "^mysql$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide "postgres datacache" tab if postgres not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification 
hide_postgres_datacache_tab[] =
+{
+  { "GNUNET_setup_datacache_postgres_hbox", "^postgres$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide advertised TCP port if port is zero.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_all_tcp_options[] =
+{
+  { "GNUNET_setup_transport_tcp_adv_port_hbox", NULL, "^0$" },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide NATed peer options.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification toggle_nat_options[] =
+{
+  { "GNUNET_setup_transport_hole_punched_checkbutton", "^YES$", NULL },
+  { "GNUNET_setup_transport_upnp_enable_checkbutton", "^YES$", NULL },
+  { "GNUNET_setup_transport_icmp_server_enable_checkbutton", "^YES$", NULL },
+  { "GNUNET_setup_transport_external_ip_hbox", "^YES$", NULL },
+  { NULL, NULL, NULL }
+};
+
+/**
+ * Hide hole-punched NATed peer options.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification 
toggle_nat_punched_options[] =
+{
+  { "GNUNET_setup_transport_upnp_enable_checkbutton", "^NO$", NULL },
+  { "GNUNET_setup_transport_icmp_server_enable_checkbutton", "^NO$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Hide internal IP options.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification toggle_internal_ip[] =
+{
+  { "GNUNET_setup_transport_internal_ip_hbox", "^YES$", NULL },
+  { NULL, NULL, NULL }
+};
+
+
+/**
+ * Option specification data.
+ */
+const struct GNUNET_SETUP_OptionSpecification option_specifications[] =
+  {
+
+    /* GENERAL TAB */
+
+    { 
+      "GNUNET_setup_friends_only_checkbutton",
+      "toggled",
+      "topology",
+      "FRIENDS-ONLY",
+      gettext_noop ("Should GNUnet exclusively connect to friends?"),
+      "https://gnunet.org/configuration-f2f";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      hide_min_connected_friends
+    },    
+
+    { 
+      "GNUNET_setup_friends_filechooserbutton",
+      "selection-changed",
+      "topology",
+      "FRIENDS",
+      gettext_noop ("Friends file containing the list of friendly peers"),
+      "https://gnunet.org/configuration-f2f";,
+      &load_filename,
+      &save_filename, NULL,
+      NULL
+    },
+
+    { 
+      "GNUNET_setup_minimum_friends_spinbutton",
+      "value-changed",
+      "topology",
+      "MINIMUM-FRIENDS",
+      gettext_noop ("Minimum number of friendly connections"),
+      "https://gnunet.org/configuration-f2f";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },    
+
+    {
+      "GNUNET_setup_general_services_topology_checkbutton",
+      "toggled",
+      "arm",
+      "DEFAULTSERVICES",
+      gettext_noop ("Topology should always be loaded"),
+      "https://gnunet.org/configuration-topology";,
+      &load_option_list,
+      &save_option_list, "topology",
+      NULL
+    },
+
+    {
+      "GNUNET_setup_general_services_hostlist_checkbutton",
+      "toggled",
+      "arm",
+      "DEFAULTSERVICES",
+      gettext_noop ("Should hostlist support be started automatically on 
startup?"),
+      "https://gnunet.org/configuration-hostlist";,
+      &load_option_list,
+      &save_option_list, "hostlist",
+      hide_hostlist_options
+    },
+
+
+    {
+      "GNUNET_setup_general_services_fs_checkbutton",
+      "toggled",
+      "arm",
+      "DEFAULTSERVICES",
+      gettext_noop ("Should file-sharing be started automatically on 
startup?"),
+      "https://gnunet.org/configuration-fs";,
+      &load_option_list,
+      &save_option_list, "fs",
+      hide_fs_tab
+    },
+
+    {
+      "GNUNET_setup_general_services_vpn_checkbutton",
+      "toggled",
+      "arm",
+      "DEFAULTSERVICES",
+      gettext_noop ("Should the VPN be started automatically on startup?"),
+      "https://gnunet.org/configuration-vpn";,
+      &load_option_list,
+      &save_option_list, "vpn",
+      hide_vpn_tab
+    },
+
+    {
+      "GNUNET_setup_hostlist_client_enable_checkbutton",
+      "toggled",
+      "hostlist",
+      "OPTIONS",
+      gettext_noop ("Should GNUnet learn about other peers using hostlists"),
+      "https://gnunet.org/configuration-hostlist";,
+      &load_option_list,
+      &save_option_list, "-b",
+      NULL
+    },
+
+    {
+      "GNUNET_setup_hostlist_client_learn_checkbutton",
+      "toggled",
+      "hostlist",
+      "OPTIONS",
+      gettext_noop ("Should GNUnet learn hostlists from other peers"),
+      "https://gnunet.org/configuration-hostlist";,
+      &load_option_list,
+      &save_option_list, "-e",
+      NULL
+    },
+
+    {
+      "GNUNET_setup_hostlist_offer_hostlist_checkbutton",
+      "toggled",
+      "hostlist",
+      "OPTIONS",
+      gettext_noop ("Should this peer offer a hostlist to other peers"),
+      "https://gnunet.org/configuration-hostlist-server";,
+      &load_option_list,
+      &save_option_list, "-p",
+      hide_hostlist_server_options
+    },
+
+    {
+      "GNUNET_setup_hostlist_advertise_checkbutton",
+      "toggled",
+      "hostlist",
+      "OPTIONS",
+      gettext_noop ("Should this peer advertise its hostlist to other peers"),
+      "https://gnunet.org/configuration-hostlist-server";,
+      &load_option_list,
+      &save_option_list, "-a",
+      NULL
+    },
+
+    {
+      "GNUNET_setup_hostlist_server_port_spin_button",
+      "value-changed",
+      "hostlist",
+      "HTTPPORT",
+      gettext_noop ("Port this peers hostlist should be offered on"),
+      "https://gnunet.org/configuration-hostlist-server";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_hostlist_url_liststore",
+      "row-changed",
+      "hostlist",
+      "SERVERS",
+      NULL, NULL,
+      &load_string_list_store,
+      &save_string_list_store, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_hostlist_url_treeview",
+      NULL, NULL, NULL, /* FIXME */
+      gettext_noop ("Known hostlist URLs"),
+      "https://gnunet.org/configuration-hostlist";,
+      NULL, NULL, NULL,  /* FIXME */
+      NULL
+    },
+
+    {
+      "GNUNET_setup_bandwidth_out_spinbutton",
+      "value-changed",
+      "core",
+      "TOTAL_QUOTA_OUT",
+      gettext_noop ("How many bytes per second are we allowed to transmit?"),
+      "https://gnunet.org/configuration-bandwidth";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_bandwidth_in_spinbutton",
+      "value-changed",
+      "core",
+      "TOTAL_QUOTA_IN",
+      gettext_noop ("How many bytes per second are we allowed to receive?"),
+      "https://gnunet.org/configuration-bandwidth";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+   
+    /* Transport TAB */
+
+    {
+      "GNUNET_setup_transport_tcp_checkbutton",
+      "toggled",
+      "transport",
+      "PLUGINS",
+      gettext_noop ("Enable communication via TCP"),
+      "https://gnunet.org/configuration-tcp";,
+      &load_option_list,
+      &save_option_list, "tcp",
+      hide_tcp_tab
+    },
+
+    {
+      "GNUNET_setup_transport_udp_checkbutton",
+      "toggled",
+      "transport",
+      "PLUGINS",
+      gettext_noop ("Enable communication via UDP"),
+      "https://gnunet.org/configuration-udp";,
+      &load_option_list,
+      &save_option_list, "udp",
+      hide_udp_tab
+    },
+
+    {
+      "GNUNET_setup_transport_http_checkbutton",
+      "toggled",
+      "transport",
+      "PLUGINS",
+      gettext_noop ("Enable communication via HTTP"),
+      "https://gnunet.org/configuration-http";,
+      &load_option_list,
+      &save_option_list, "http",
+      hide_http_tab
+    },
+
+    {
+      "GNUNET_setup_transport_https_checkbutton",
+      "toggled",
+      "transport",
+      "PLUGINS",
+      gettext_noop ("Enable communication via HTTPS"),
+      "https://gnunet.org/configuration-https";,
+      &load_option_list,
+      &save_option_list, "https",
+      hide_https_tab
+    },
+
+    {
+      "GNUNET_setup_transport_dv_checkbutton",
+      "toggled",
+      "transport",
+      "PLUGINS",
+      gettext_noop ("Enable communication via DV"),
+      "https://gnunet.org/configuration-dv";,
+      &load_option_list,
+      &save_option_list, "dv",
+      hide_dv_tab
+    },
+
+    {
+      "GNUNET_setup_transport_wlan_checkbutton",
+      "toggled",
+      "transport",
+      "PLUGINS",
+      gettext_noop ("Enable communication via WLAN"),
+      "https://gnunet.org/configuration-wlan";,
+      &load_option_list,
+      &save_option_list, "wlan",
+      hide_wlan_tab
+    },
+
+    {
+      "GNUNET_setup_transport_tcp_port_spinbutton",
+      "value-changed",
+      "transport-tcp",
+      "PORT",
+      gettext_noop ("Port we bind to for TCP"),
+      "https://gnunet.org/configuration-tcp";,
+      &load_number,
+      &save_number, NULL,
+      hide_all_tcp_options
+    },
+
+    {
+      "GNUNET_setup_transport_tcp_adv_port_spinbutton",
+      "value-changed",
+      "transport-tcp",
+      "ADVERTISED_PORT",
+      gettext_noop ("Port visible to other peers"),
+      "https://gnunet.org/configuration-tcp";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_transport_nat_checkbutton",
+      "toggled",
+      "nat",
+      "BEHIND_NAT",
+      gettext_noop ("Check if this peer is behind a NAT"),
+      "https://gnunet.org/configuration-nat";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      toggle_nat_options
+    },
+
+    {
+      "GNUNET_setup_transport_hole_punched_checkbutton",
+      "toggled",
+      "nat",
+      "PUNCHED_NAT",
+      gettext_noop ("Check if the NAT has been hole-punched manually"),
+      "https://gnunet.org/configuration-nat";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      toggle_nat_punched_options
+    },
+
+    {
+      "GNUNET_setup_transport_upnp_enable_checkbutton",
+      "toggled",
+      "nat",
+      "ENABLE_UPNP",
+      gettext_noop ("Enable NAT traversal with UPnP/PMP"),
+      "https://gnunet.org/configuration-nat";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL,
+    },
+
+    {
+      "GNUNET_setup_transport_icmp_server_enable_checkbutton",
+      "toggled",
+      "nat",
+      "ENABLE_ICMP_SERVER",
+      gettext_noop ("Enable NAT traversal with ICMP as server"),
+      "https://gnunet.org/configuration-nat";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL,
+    },
+
+    {
+      "GNUNET_setup_transport_external_ip_address_entry",
+      "changed",
+      "nat",
+      "EXTERNAL_ADDRESS",
+      gettext_noop ("External (public) IP address of the NAT"),
+      "https://gnunet.org/configuration-nat";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_transport_icmp_client_enable_checkbutton",
+      "toggled",
+      "nat",
+      "ENABLE_ICMP_CLIENT",
+      gettext_noop ("Enable NAT traversal with ICMP as client"),
+      "https://gnunet.org/configuration-nat";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      toggle_internal_ip
+    },
+
+    {
+      "GNUNET_setup_transport_internal_ip_entry",
+      "changed",
+      "nat",
+      "INTERNAL_ADDRESS",
+      gettext_noop ("Internal (private) IP address of the NAT"),
+      "https://gnunet.org/configuration-nat";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_transport_disable_ipv6_checkbutton",
+      "toggled",
+      "nat",
+      "DISABLEV6",
+      gettext_noop ("Disable IPv6 support"),
+      "https://gnunet.org/configuration-ipv6";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL,
+    },
+
+    {
+      "GNUNET_setup_transport_udp_port_spinbutton",
+      "value-changed",
+      "transport-udp",
+      "PORT",
+      gettext_noop ("Port for inbound UDP packets, use 0 if behind NAT"),
+      "https://gnunet.org/configuration-udp";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_transport_http_port_spinbutton",
+      "value-changed",
+      "transport-http",
+      "PORT",
+      gettext_noop ("Port for inbound HTTP connections, use 0 if behind NAT"),
+      "https://gnunet.org/configuration-http";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_transport_https_port_spinbutton",
+      "value-changed",
+      "transport-https",
+      "PORT",
+      gettext_noop ("Port for inbound HTTPS connections, use 0 if behind NAT"),
+      "https://gnunet.org/configuration-https";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    /* FS TAB */
+    
+    {
+      "GNUNET_setup_fs_datastore_sqlite_radiobutton",
+      "toggled",
+      "datastore",
+      "DATABASE",
+      gettext_noop ("Use sqLite to store file-sharing content"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_option_list /* abuse! */,
+      &save_option_list /* abuse! */, "sqlite",
+      hide_sqlite_datastore_tab
+    },
+
+    {
+      "GNUNET_setup_fs_datastore_mysql_radiobutton",
+      "toggled",
+      "datastore",
+      "DATABASE",
+      gettext_noop ("Use MySQL to store file-sharing content"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_option_list /* abuse! */,
+      &save_option_list /* abuse! */, "mysql",
+      hide_mysql_datastore_tab
+    },
+
+    {
+      "GNUNET_setup_fs_datastore_postgres_radiobutton",
+      "toggled",
+      "datastore",
+      "DATABASE",
+      gettext_noop ("Use Postgres to store file-sharing content"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_option_list /* abuse! */,
+      &save_option_list /* abuse! */, "postgres",
+      hide_postgres_datastore_tab
+    },
+
+    {
+      "GNUNET_setup_datastore_mysql_database_name_entry",
+      "changed",
+      "datastore-mysql",
+      "DATABASE",
+      gettext_noop ("Name for the MySQL database"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    { 
+      "GNUNET_setup_datastore_mysql_config_file_filechooserbutton",
+      "selection-changed",
+      "datastore-mysql",
+      "CONFIG",
+      gettext_noop ("Configuration file for MySQL access"),
+      "http://dev.mysql.com/doc/refman/5.5/en/option-files.html";,
+      &load_filename,
+      &save_filename, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datastore_mysql_username_entry",
+      "changed",
+      "datastore-mysql",
+      "USER",
+      gettext_noop ("Username for MySQL access"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datastore_mysql_password_entry",
+      "changed",
+      "datastore-mysql",
+      "PASSWORD",
+      gettext_noop ("Password for MySQL access"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datastore_mysql_hostname_entry",
+      "changed",
+      "datastore-mysql",
+      "HOST",
+      gettext_noop ("Name of host running MySQL database"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datastore_mysql_port_spinbutton",
+      "value-changed",
+      "datastore-mysql",
+      "PORT",
+      gettext_noop ("Port of MySQL database"),
+      "https://gnunet.org/configuration-datastore";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datastore_postgres_config_entry",
+      "changed",
+      "datastore-postgres",
+      "CONFIG",
+      gettext_noop ("Configuration for Postgres (passed to PQconnectdb)"),
+      "http://www.postgresql.org/docs/8.1/static/libpq.html#LIBPQ-CONNECT";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    
+    { 
+      "GNUNET_setup_fs_migration_from_checkbutton",
+      "toggled",
+      "fs",
+      "CONTENT_PUSHING",
+      gettext_noop ("Should we try to push our content to other peers?"),
+      "https://gnunet.org/configuration-fs";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL
+    },    
+
+    { 
+      "GNUNET_setup_fs_migration_to_checkbutton",
+      "toggled",
+      "fs",
+      "CONTENT_CACHING",
+      gettext_noop ("Are we allowed to cache content received from other 
peers?"),
+      "https://gnunet.org/configuration-fs";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL
+    },    
+    
+    {
+      "GNUNET_setup_fs_datacache_sqlite_radiobutton",
+      "toggled",
+      "dhtcache",
+      "DATABASE",
+      gettext_noop ("Use sqLite to cache DHT data"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_option_list /* abuse! */,
+      &save_option_list /* abuse! */, "sqlite",
+      hide_sqlite_datacache_tab
+    },
+
+    {
+      "GNUNET_setup_fs_datacache_mysql_radiobutton",
+      "toggled",
+      "dhtcache",
+      "DATABASE",
+      gettext_noop ("Use MySQL to cache DHT data"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_option_list /* abuse! */,
+      &save_option_list /* abuse! */, "mysql",
+      hide_mysql_datacache_tab
+    },
+
+    {
+      "GNUNET_setup_fs_datacache_postgres_radiobutton",
+      "toggled",
+      "dhtcache",
+      "DATABASE",
+      gettext_noop ("Use Postgres to cache DHT data"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_option_list /* abuse! */,
+      &save_option_list /* abuse! */, "postgres",
+      hide_postgres_datacache_tab
+    },
+  
+    {
+      "GNUNET_setup_datacache_mysql_database_name_entry",
+      "changed",
+      "datacache-mysql",
+      "DATABASE",
+      gettext_noop ("Name for the MySQL database"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    { 
+      "GNUNET_setup_datacache_mysql_config_file_filechooserbutton",
+      "selection-changed",
+      "datacache-mysql",
+      "CONFIG",
+      gettext_noop ("Configuration file for MySQL access"),
+      "http://dev.mysql.com/doc/refman/5.5/en/option-files.html";,
+      &load_filename,
+      &save_filename, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datacache_mysql_username_entry",
+      "changed",
+      "datacache-mysql",
+      "USER",
+      gettext_noop ("Username for MySQL access"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datacache_mysql_password_entry",
+      "changed",
+      "datacache-mysql",
+      "PASSWORD",
+      gettext_noop ("Password for MySQL access"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datacache_mysql_hostname_entry",
+      "changed",
+      "datacache-mysql",
+      "HOST",
+      gettext_noop ("Name of host running MySQL database"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_transport_wlan_interface_entry",
+      "changed",
+      "transport-wlan",
+      "INTERFACE",
+      gettext_noop ("Name of monitoring interface to use (monX)"),
+      "https://gnunet.org/configuration-wlan";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datacache_mysql_port_spinbutton",
+      "value-changed",
+      "datacache-mysql",
+      "PORT",
+      gettext_noop ("Port of MySQL database"),
+      "https://gnunet.org/configuration-datacache";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },
+
+    {
+      "GNUNET_setup_datacache_postgres_config_entry",
+      "changed",
+      "datacache-postgres",
+      "CONFIG",
+      gettext_noop ("Configuration for Postgres (passed to PQconnectdb)"),
+      "http://www.postgresql.org/docs/8.1/static/libpq.html#LIBPQ-CONNECT";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+    
+    {
+      "GNUNET_setup_vpn_master_interface_entry",
+      "changed",
+      "vpn",
+      "IFNAME",
+      gettext_noop ("Name of the virtual interface the GNUnet VPN should 
create"),
+      "https://gnunet.org/configuration-vpn";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },
+     
+    {
+      "GNUNET_setup_vpn_master_interface_v4_ip_entry",
+      "changed",
+      "vpn",
+      "IPV4ADDR",
+      gettext_noop ("IPv4 address to use for the VPN interface"),
+      "https://gnunet.org/configuration-vpn";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },  
+   
+    {
+      "GNUNET_setup_vpn_master_interface_v4_mask_entry",
+      "changed",
+      "vpn",
+      "IPV4MASK",
+      gettext_noop ("IPv4 network mask to use for the VPN interface"),
+      "https://gnunet.org/configuration-vpn";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },    
+   
+    {
+      "GNUNET_setup_vpn_master_interface_v6_ip_entry",
+      "changed",
+      "vpn",
+      "IPV6ADDR",
+      gettext_noop ("IPv6 address to use for the VPN interface"),
+      "https://gnunet.org/configuration-vpn";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },  
+   
+    {
+      "GNUNET_setup_vpn_master_interface_v6_mask_spinbutton",
+      "value-changed",
+      "vpn",
+      "IPV6MASK",
+      gettext_noop ("IPv6 network prefix length to use for the VPN interface"),
+      "https://gnunet.org/configuration-vpn";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },    
+
+    {
+      "GNUNET_setup_vpn_master_vdns_server_entry",
+      "changed",
+      "vpn",
+      "VIRTDNS",
+      gettext_noop ("IP address of the virtual DNS server that resolves 
through GNUnet (use in resolve.conf if you want to resolve through some GNUnet 
DNS Exit)"),
+      "https://gnunet.org/configuration-vpn";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },    
+
+    {
+      "GNUNET_setup_vpn_enable_vpn_exit_checkbutton",
+      "toggled",
+      "arm",
+      "DEFAULTSERVICES",
+      gettext_noop ("Activate the VPN exit to provide services and/or to 
enable others to use your Internet connection"),
+      "https://gnunet.org/configuration-exit";,
+      &load_option_list,
+      &save_option_list, "exit",
+      hide_exit_options
+    },    
+
+    {
+      "GNUNET_setup_vpn_enable_dns_exit_checkbutton",
+      "toggled",
+      "dns",
+      "PROVIDE_EXIT",
+      gettext_noop ("Allow other peers to perform DNS resolutions using your 
Internet connection"),
+      "https://gnunet.org/configuration-dns";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL
+    },    
+
+    {
+      "GNUNET_setup_vpn_exit_interface_name_entry",
+      "changed",
+      "exit",
+      "IFNAME",
+      gettext_noop ("Name of the virtual interface the GNUnet exit service 
should create for traffic exiting the VPN to the Internet"),
+      "https://gnunet.org/configuration-exit";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    }, 
+   
+    {
+      "GNUNET_setup_vpn_exit_interface_v4_ip_entry",
+      "changed",
+      "exit",
+      "IPV4ADDR",
+      gettext_noop ("IPv4 address to use for the VPN Exit interface"),
+      "https://gnunet.org/configuration-exit";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },  
+   
+    {
+      "GNUNET_setup_vpn_exit_interface_v4_mask_entry",
+      "changed",
+      "exit",
+      "IPV4MASK",
+      gettext_noop ("IPv4 network mask to use for the VPN Exit interface"),
+      "https://gnunet.org/configuration-exit";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },    
+   
+    {
+      "GNUNET_setup_vpn_exit_interface_v6_ip_entry",
+      "changed",
+      "exit",
+      "IPV6ADDR",
+      gettext_noop ("IPv6 address to use for the VPN Exit interface"),
+      "https://gnunet.org/configuration-exit";,
+      &load_text,
+      &save_text, NULL,
+      NULL
+    },  
+   
+    {
+      "GNUNET_setup_vpn_exit_interface_v6_mask_spinbutton",
+      "value-changed",
+      "exit",
+      "IPV6MASK",
+      gettext_noop ("IPv6 network prefix length to use for the VPN Exit 
interface"),
+      "https://gnunet.org/configuration-exit";,
+      &load_number,
+      &save_number, NULL,
+      NULL
+    },    
+
+
+    {
+      "GNUNET_setup_vpn_exit_enable_udp_checkbutton",
+      "toggled",
+      "exit",
+      "ENABLE_UDP",
+      gettext_noop ("Allow other users to use your Internet connection for UDP 
traffic (via the Exit interface)"),
+      "https://gnunet.org/configuration-exit";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL
+    },
+    
+    {
+      "GNUNET_setup_vpn_exit_enable_tcp_checkbutton",
+      "toggled",
+      "exit",
+      "ENABLE_TCP",
+      gettext_noop ("Allow other users to use your Internet connection for TCP 
traffic (via the Exit interface)"),
+      "https://gnunet.org/configuration-exit";,
+      &load_yes_no,
+      &save_yes_no, NULL,
+      NULL
+    },
+
+    /* DNS treeview */
+    
+    {
+      "GNUNET_setup_vpn_dns_service_treeview",
+      NULL,
+      NULL,
+      NULL,
+      gettext_noop ("Specification of .gnunet hostnames and services offered 
by this peer"),
+      "https://gnunet.org/configuration-dns";,
+      &load_vpn_dns_configuration,
+      NULL, NULL,
+      NULL
+    },
+        
+    {
+      "GNUNET_setup_vpn_dns_service_dnsname_cellrenderertext",
+      "editing-started",
+      NULL,
+      NULL,
+      NULL,
+      "https://gnunet.org/configuration-dns";,
+      NULL,
+      &vpn_dns_service_dnsname_install_edited_handler,
+      NULL,
+      NULL
+    },        
+
+    {
+      "GNUNET_setup_vpn_dns_service_tcpudp_cellrenderertext",
+      "editing-started",
+      NULL,
+      NULL,
+      NULL,
+      "https://gnunet.org/configuration-dns";,
+      NULL,
+      &vpn_dns_service_tcpudp_install_edited_handler,
+      NULL,
+      NULL
+    },        
+
+    {
+      "GNUNET_setup_vpn_dns_service_sourceport_cellrenderertext",
+      "editing-started",
+      NULL,
+      NULL,
+      NULL,
+      "https://gnunet.org/configuration-dns";,
+      NULL,
+      &vpn_dns_service_sourceport_install_edited_handler,
+      NULL,
+      NULL
+    },
+       
+    {
+      "GNUNET_setup_vpn_dns_service_targethostname_cellrenderertext",
+      "editing-started",
+      NULL,
+      NULL,
+      NULL,
+      "https://gnunet.org/configuration-dns";,
+      NULL,
+      &vpn_dns_service_targethostname_install_edited_handler,
+      NULL,
+      NULL
+    },
+        
+    {
+      "GNUNET_setup_vpn_dns_service_targetport_cellrenderertext",
+      "editing-started",
+      NULL,
+      NULL,
+      NULL,
+      "https://gnunet.org/configuration-dns";,
+      NULL,
+      &vpn_dns_service_targetport_install_edited_handler,
+      NULL,
+      NULL
+    },        
+
+    /* END of list */
+
+    { NULL, NULL, NULL, NULL, NULL,
+      NULL, NULL, NULL, NULL }
+  };
+
+/* end of gnunet-setup-options.c */

Copied: gnunet-gtk/src/setup/gnunet-setup-options.h (from rev 16514, 
gnunet-setup/src/gnunet-setup-options.h)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-options.h                         (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-options.h 2011-08-15 14:15:47 UTC (rev 
16546)
@@ -0,0 +1,161 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-options.h
+ * @brief configuration details
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SETUP_OPTIONS_H
+#define GNUNET_SETUP_OPTIONS_H
+
+#include "gnunet-setup.h"
+
+
+/**
+ * Function to setup the value on load.
+ *
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param value value as a string
+ * @param widget widget to initialize
+ * @param cfg configuration handle
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+typedef int (*GNUNET_SETUP_LoadFunction)(const void *cls,
+                                        const char *section,
+                                        const char *option,
+                                        const char *value,
+                                        GObject *widget,
+                                        const struct 
GNUNET_CONFIGURATION_Handle *cfg);
+
+
+/**
+ * Modify the configuration to contain the right value for
+ * the option based on the state of the widget.
+ * 
+ * @param cls closure
+ * @param section section with the value
+ * @param option option name
+ * @param widget widget to initialize
+ * @param cfg configuration handle to update
+ * @return GNUNET_OK on success, GNUNET_SYSERR if there was a problem
+ */
+typedef int (*GNUNET_SETUP_SaveFunction)(const void *cls,
+                                        const char *section,
+                                        const char *option,
+                                        GObject *widget,
+                                        struct GNUNET_CONFIGURATION_Handle 
*cfg);
+
+
+/**
+ * Structs of this type specify under which conditions the values of
+ * a particular option impact the visibility (or sensitivity) of some
+ * other widget.
+ */
+struct GNUNET_SETUP_VisibilitySpecification
+{
+  /**
+   * Which widget should be changed?
+   */
+  const char *widget_name;
+
+  /**
+   * If the option value matchis this regex, the widget should be
+   * shown.  If NULL, the "hide_value" controls visibility.
+   */
+  const char *show_value;
+
+  /**
+   * If the option value matchis this regex, the widget should be
+   * hidden.  If NULL, the "show_value" controls visibility.
+   */  
+  const char *hide_value;
+
+};
+
+
+/**
+ * Structs of this type define how widgets relate to GNUnet options
+ * and control visibility and special actions.
+ */
+struct GNUNET_SETUP_OptionSpecification
+{
+  /**
+   * Name of the GTK widget in Glade.
+   */
+  const char *widget_name;
+
+  /**
+   * Name of the signal the widget emits if its state changes.
+   */
+  const char *change_signal;
+
+  /**
+   * Section in the configuration
+   */
+  const char *section;
+
+  /**
+   * Name of the configuration option.
+   */
+  const char *option;
+
+  /**
+   * Help text to display for this option.
+   */
+  const char *help_text;
+
+  /**
+   * Help URL to link to for this option.
+   */
+  const char *help_url;
+
+  /**
+   * Function to call to initialize the widget from the configuration.
+   */
+  GNUNET_SETUP_LoadFunction load_function;
+
+  /**
+   * Function to call set the configuration from the widget.
+   */
+  GNUNET_SETUP_SaveFunction save_function;
+
+  /**
+   * Closure for 'validation_function'.
+   */
+  const void *load_save_cls;
+
+  /**
+   * Visibility changes to apply if this option changes (NULL, or
+   * NULL-terminated).
+   */
+  const struct GNUNET_SETUP_VisibilitySpecification *visibility;
+
+};
+
+
+/**
+ * Option specification data.
+ */
+extern const struct GNUNET_SETUP_OptionSpecification option_specifications[];
+
+#endif

Copied: gnunet-gtk/src/setup/gnunet-setup-transport-http.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-transport-http.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-transport-http.c                          
(rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-transport-http.c  2011-08-15 14:15:47 UTC 
(rev 16546)
@@ -0,0 +1,182 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-transport-http.c
+ * @brief support for HTTP configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_resolver_service.h>
+#include <gnunet/gnunet_nat_lib.h>
+
+/**
+ * How long do we wait for the NAT test to report success?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+
+/**
+ * Handle to the active NAT test.
+ */
+static struct GNUNET_NAT_Test *tst;
+
+/**
+ * Task identifier for the timeout.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier tsk;
+
+
+/**
+ * Function called by NAT on success.
+ * Clean up and update GUI (with success).
+ *
+ * @param cls closure (unused)
+ * @param success currently always GNUNET_OK
+ */
+static void
+result_callback (void *cls,
+                int success)
+{
+  int *ok = cls;
+
+  *ok = success;
+  GNUNET_SCHEDULER_cancel (tsk);
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Function called if NAT failed to confirm success.
+ * Clean up and update GUI (with failure).
+ *
+ * @param cls closure (unused)
+ * @param tc scheduler callback
+ */
+static void
+fail_timeout (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  
+  GNUNET_assert (NULL != tst);
+  *ok = GNUNET_NO;
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Main function for the NAT test.
+ *
+ * @param cls the 'int*' for the result
+ * @param tc scheduler context
+ */
+static void 
+test (void *cls,
+      const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  unsigned long long bnd_port;
+  unsigned long long adv_port;
+
+  GNUNET_assert (NULL != cfg);
+  GNUNET_RESOLVER_connect (cfg);
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-http",
+                                            "PORT",
+                                            &bnd_port))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-http",
+                                            "ADVERTISED_PORT",
+                                            &adv_port))
+    adv_port = bnd_port;
+  tst = GNUNET_NAT_test_start (cfg,
+                              GNUNET_YES,
+                              (uint16_t) bnd_port,
+                              (uint16_t) adv_port,
+                              &result_callback,
+                              ok);
+  if (NULL == tst)
+    {
+      *ok = GNUNET_SYSERR;
+      return;
+    }
+  tsk = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                     &fail_timeout,
+                                     ok);
+}
+
+/**
+ * Function called whenever the user wants to test the
+ * HTTP configuration.
+ */
+void
+GNUNET_setup_transport_http_test_button_clicked_cb ()
+{
+  GtkWidget *w;
+  int ok;
+  struct GNUNET_OS_Process *resolver;
+
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tsk);
+  GNUNET_assert (NULL == tst);
+  w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                         
"GNUNET_setup_transport_http_test_success_image"));
+  gtk_widget_hide (w);
+  resolver = GNUNET_OS_start_process (NULL, NULL,
+                                     "gnunet-service-resolver", 
+                                     "gnunet-service-resolver", NULL);
+  ok = GNUNET_NO;
+  GNUNET_SCHEDULER_run (&test, &ok);
+  if (NULL != resolver)
+    {
+      GNUNET_break (0 == GNUNET_OS_process_kill (resolver, SIGTERM));
+      GNUNET_OS_process_close (resolver);
+    }
+  if (GNUNET_YES != ok)
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_http_test_fail_image"));
+      gtk_widget_show (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_http_test_success_image"));
+      gtk_widget_hide (w);
+    }
+  else
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_http_test_fail_image"));
+      gtk_widget_hide (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_http_test_success_image"));
+      gtk_widget_show (w);
+    }
+}
+
+
+/* end of gnunet-setup-transport-http.c */

Copied: gnunet-gtk/src/setup/gnunet-setup-transport-https.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-transport-https.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-transport-https.c                         
(rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-transport-https.c 2011-08-15 14:15:47 UTC 
(rev 16546)
@@ -0,0 +1,182 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-transport-https.c
+ * @brief support for HTTPS configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_resolver_service.h>
+#include <gnunet/gnunet_nat_lib.h>
+
+/**
+ * How long do we wait for the NAT test to report success?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+
+/**
+ * Handle to the active NAT test.
+ */
+static struct GNUNET_NAT_Test *tst;
+
+/**
+ * Task identifier for the timeout.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier tsk;
+
+
+/**
+ * Function called by NAT on success.
+ * Clean up and update GUI (with success).
+ *
+ * @param cls closure (unused)
+ * @param success currently always GNUNET_OK
+ */
+static void
+result_callback (void *cls,
+                int success)
+{
+  int *ok = cls;
+
+  *ok = success;
+  GNUNET_SCHEDULER_cancel (tsk);
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Function called if NAT failed to confirm success.
+ * Clean up and update GUI (with failure).
+ *
+ * @param cls closure (unused)
+ * @param tc scheduler callback
+ */
+static void
+fail_timeout (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  
+  GNUNET_assert (NULL != tst);
+  *ok = GNUNET_NO;
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Main function for the NAT test.
+ *
+ * @param cls the 'int*' for the result
+ * @param tc scheduler context
+ */
+static void 
+test (void *cls,
+      const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  unsigned long long bnd_port;
+  unsigned long long adv_port;
+
+  GNUNET_assert (NULL != cfg);
+  GNUNET_RESOLVER_connect (cfg);
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-https",
+                                            "PORT",
+                                            &bnd_port))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-https",
+                                            "ADVERTISED_PORT",
+                                            &adv_port))
+    adv_port = bnd_port;
+  tst = GNUNET_NAT_test_start (cfg,
+                              GNUNET_YES,
+                              (uint16_t) bnd_port,
+                              (uint16_t) adv_port,
+                              &result_callback,
+                              ok);
+  if (NULL == tst)
+    {
+      *ok = GNUNET_SYSERR;
+      return;
+    }
+  tsk = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                     &fail_timeout,
+                                     ok);
+}
+
+/**
+ * Function called whenever the user wants to test the
+ * HTTPS configuration.
+ */
+void
+GNUNET_setup_transport_https_test_button_clicked_cb ()
+{
+  GtkWidget *w;
+  int ok;
+  struct GNUNET_OS_Process *resolver;
+
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tsk);
+  GNUNET_assert (NULL == tst);
+  w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                         
"GNUNET_setup_transport_https_test_success_image"));
+  gtk_widget_hide (w);
+  resolver = GNUNET_OS_start_process (NULL, NULL,
+                                     "gnunet-service-resolver", 
+                                     "gnunet-service-resolver", NULL);
+  ok = GNUNET_NO;
+  GNUNET_SCHEDULER_run (&test, &ok);
+  if (NULL != resolver)
+    {
+      GNUNET_break (0 == GNUNET_OS_process_kill (resolver, SIGTERM));
+      GNUNET_OS_process_close (resolver);
+    }
+  if (GNUNET_YES != ok)
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_https_test_fail_image"));
+      gtk_widget_show (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_https_test_success_image"));
+      gtk_widget_hide (w);
+    }
+  else
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_https_test_fail_image"));
+      gtk_widget_hide (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_https_test_success_image"));
+      gtk_widget_show (w);
+    }
+}
+
+
+/* end of gnunet-setup-transport-https.c */

Copied: gnunet-gtk/src/setup/gnunet-setup-transport-plugins.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-transport-plugins.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-transport-plugins.c                       
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-transport-plugins.c       2011-08-15 
14:15:47 UTC (rev 16546)
@@ -0,0 +1,105 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-transport-plugins.c
+ * @brief (de)sensitize transport plugin buttons based on plugin availability
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+
+
+/**
+ * Test if the given plugin exists and change the sensitivity
+ * of the widget accordingly.
+ *
+ * @param widget widget to update
+ * @param name name of the plugin to check
+ */
+static void
+test_plugin (GtkWidget *widget,
+            const char *name)
+{
+  if (GNUNET_YES ==
+      GNUNET_PLUGIN_test (name))
+    {
+      gtk_widget_set_sensitive (widget, 
+                               TRUE);
+    }
+  else
+    {
+      gtk_widget_set_sensitive (widget, 
+                               FALSE);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), 
+                                   FALSE);
+    }
+}
+
+
+
+void
+GNUNET_setup_transport_tcp_checkbutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_transport_tcp");
+}
+
+
+void
+GNUNET_setup_transport_udp_checkbutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_transport_udp");
+}
+
+
+void
+GNUNET_setup_transport_http_checkbutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_transport_http");
+}
+
+
+void
+GNUNET_setup_transport_https_checkbutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_transport_https");
+}
+
+
+void
+GNUNET_setup_transport_dv_checkbutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_transport_dv");
+}
+
+
+void
+GNUNET_setup_transport_wlan_checkbutton_realize_cb (GtkWidget *widget,
+                                                  gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_transport_wlan");
+}
+
+/* end of gnunet-setup-transport-plugins.c */
+

Copied: gnunet-gtk/src/setup/gnunet-setup-transport-tcp.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-transport-tcp.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-transport-tcp.c                           
(rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-transport-tcp.c   2011-08-15 14:15:47 UTC 
(rev 16546)
@@ -0,0 +1,182 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-transport-tcp.c
+ * @brief support for TCP configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_resolver_service.h>
+#include <gnunet/gnunet_nat_lib.h>
+
+/**
+ * How long do we wait for the NAT test to report success?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+
+/**
+ * Handle to the active NAT test.
+ */
+static struct GNUNET_NAT_Test *tst;
+
+/**
+ * Task identifier for the timeout.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier tsk;
+
+
+/**
+ * Function called by NAT on success.
+ * Clean up and update GUI (with success).
+ *
+ * @param cls closure (unused)
+ * @param success currently always GNUNET_OK
+ */
+static void
+result_callback (void *cls,
+                int success)
+{
+  int *ok = cls;
+
+  *ok = success;
+  GNUNET_SCHEDULER_cancel (tsk);
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Function called if NAT failed to confirm success.
+ * Clean up and update GUI (with failure).
+ *
+ * @param cls closure (unused)
+ * @param tc scheduler callback
+ */
+static void
+fail_timeout (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  
+  GNUNET_assert (NULL != tst);
+  *ok = GNUNET_NO;
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Main function for the NAT test.
+ *
+ * @param cls the 'int*' for the result
+ * @param tc scheduler context
+ */
+static void 
+test (void *cls,
+      const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  unsigned long long bnd_port;
+  unsigned long long adv_port;
+
+  GNUNET_assert (NULL != cfg);
+  GNUNET_RESOLVER_connect (cfg);
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-tcp",
+                                            "PORT",
+                                            &bnd_port))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-tcp",
+                                            "ADVERTISED_PORT",
+                                            &adv_port))
+    adv_port = bnd_port;
+  tst = GNUNET_NAT_test_start (cfg,
+                              GNUNET_YES,
+                              (uint16_t) bnd_port,
+                              (uint16_t) adv_port,
+                              &result_callback,
+                              ok);
+  if (NULL == tst)
+    {
+      *ok = GNUNET_SYSERR;
+      return;
+    }
+  tsk = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                     &fail_timeout,
+                                     ok);
+}
+
+/**
+ * Function called whenever the user wants to test the
+ * TCP configuration.
+ */
+void
+GNUNET_setup_transport_tcp_test_button_clicked_cb ()
+{
+  GtkWidget *w;
+  int ok;
+  struct GNUNET_OS_Process *resolver;
+
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tsk);
+  GNUNET_assert (NULL == tst);
+  w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                         
"GNUNET_setup_transport_tcp_test_success_image"));
+  gtk_widget_hide (w);
+  resolver = GNUNET_OS_start_process (NULL, NULL,
+                                     "gnunet-service-resolver", 
+                                     "gnunet-service-resolver", NULL);
+  ok = GNUNET_NO;
+  GNUNET_SCHEDULER_run (&test, &ok);
+  if (NULL != resolver)
+    {
+      GNUNET_break (0 == GNUNET_OS_process_kill (resolver, SIGTERM));
+      GNUNET_OS_process_close (resolver);
+    }
+  if (GNUNET_YES != ok)
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_tcp_test_fail_image"));
+      gtk_widget_show (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_tcp_test_success_image"));
+      gtk_widget_hide (w);
+    }
+  else
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_tcp_test_fail_image"));
+      gtk_widget_hide (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_tcp_test_success_image"));
+      gtk_widget_show (w);
+    }
+}
+
+
+/* end of gnunet-setup-transport-tcp.c */

Copied: gnunet-gtk/src/setup/gnunet-setup-transport-udp.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-transport-udp.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-transport-udp.c                           
(rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-transport-udp.c   2011-08-15 14:15:47 UTC 
(rev 16546)
@@ -0,0 +1,181 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-transport-udp.c
+ * @brief support for UDP configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_resolver_service.h>
+#include <gnunet/gnunet_nat_lib.h>
+
+/**
+ * How long do we wait for the NAT test to report success?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+
+/**
+ * Handle to the active NAT test.
+ */
+static struct GNUNET_NAT_Test *tst;
+
+/**
+ * Task identifier for the timeout.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier tsk;
+
+
+/**
+ * Function called by NAT on success.
+ * Clean up and update GUI (with success).
+ *
+ * @param cls closure (unused)
+ * @param success currently always GNUNET_OK
+ */
+static void
+result_callback (void *cls,
+                int success)
+{
+  int *ok = cls;
+
+  *ok = success;
+  GNUNET_SCHEDULER_cancel (tsk);
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Function called if NAT failed to confirm success.
+ * Clean up and update GUI (with failure).
+ *
+ * @param cls closure (unused)
+ * @param tc scheduler callback
+ */
+static void
+fail_timeout (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+
+  *ok = GNUNET_NO;
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Main function for the NAT test.
+ *
+ * @param cls the 'int*' for the result
+ * @param tc scheduler context
+ */
+static void 
+test (void *cls,
+      const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  unsigned long long bnd_port;
+  unsigned long long adv_port;
+
+  GNUNET_assert (NULL != cfg);
+  GNUNET_RESOLVER_connect (cfg);
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-udp",
+                                            "PORT",
+                                            &bnd_port))
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                            "transport-udp",
+                                            "ADVERTISED_PORT",
+                                            &adv_port))
+    adv_port = bnd_port;
+  tst = GNUNET_NAT_test_start (cfg,
+                              GNUNET_NO,
+                              (uint16_t) bnd_port,
+                              (uint16_t) adv_port,
+                              &result_callback,
+                              ok);
+  if (NULL == tst)
+    {
+      *ok = GNUNET_SYSERR;
+      return;
+    }
+  tsk = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                     &fail_timeout,
+                                     ok);
+}
+
+/**
+ * Function called whenever the user wants to test the
+ * UDP configuration.
+ */
+void
+GNUNET_setup_transport_udp_test_button_clicked_cb ()
+{
+  GtkWidget *w;
+  int ok;
+  struct GNUNET_OS_Process *resolver;
+
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tsk);
+  GNUNET_assert (NULL == tst);
+  w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                         
"GNUNET_setup_transport_udp_test_success_image"));
+  gtk_widget_hide (w);
+  resolver = GNUNET_OS_start_process (NULL, NULL,
+                                     "gnunet-service-resolver", 
+                                     "gnunet-service-resolver", NULL);
+  ok = GNUNET_NO;
+  GNUNET_SCHEDULER_run (&test, &ok);
+  if (NULL != resolver)
+    {
+      GNUNET_break (0 == GNUNET_OS_process_kill (resolver, SIGTERM));
+      GNUNET_OS_process_close (resolver);
+    }
+  if (GNUNET_YES != ok)
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_udp_test_fail_image"));
+      gtk_widget_show (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_udp_test_success_image"));
+      gtk_widget_hide (w);
+    }
+  else
+    {
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_udp_test_fail_image"));
+      gtk_widget_hide (w);
+      w = GTK_WIDGET (gtk_builder_get_object (builder,
+                                             
"GNUNET_setup_transport_udp_test_success_image"));
+      gtk_widget_show (w);
+    }
+}
+
+
+/* end of gnunet-setup-transport-udp.c */

Copied: gnunet-gtk/src/setup/gnunet-setup-transport.c (from rev 16514, 
gnunet-setup/src/gnunet-setup-transport.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-transport.c                               
(rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-transport.c       2011-08-15 14:15:47 UTC 
(rev 16546)
@@ -0,0 +1,300 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup-transport.c
+ * @brief support for transport (NAT) configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_resolver_service.h>
+#include <gnunet/gnunet_nat_lib.h>
+
+/**
+ * How long do we wait for the NAT test to report success?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+
+/**
+ * Handle to the active NAT test.
+ */
+static struct GNUNET_NAT_Test *tst;
+
+/**
+ * Task identifier for the timeout.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier tsk;
+
+
+/**
+ * Function called by NAT on success.
+ * Clean up and update GUI (with success).
+ *
+ * @param cls closure (unused)
+ * @param success currently always GNUNET_OK
+ */
+static void
+result_callback (void *cls,
+                int success)
+{
+  int *ok = cls;
+
+  *ok = success;
+  GNUNET_SCHEDULER_cancel (tsk);
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Function called if NAT failed to confirm success.
+ * Clean up and update GUI (with failure).
+ *
+ * @param cls closure (unused)
+ * @param tc scheduler callback
+ */
+static void
+fail_timeout (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+  
+  GNUNET_assert (NULL != tst);
+  *ok = GNUNET_NO;
+  tsk = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+/**
+ * Main function for the connection reversal test.
+ *
+ * @param cls the 'int*' for the result
+ * @param tc scheduler context
+ */
+static void 
+reversal_test (void *cls,
+              const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int *ok = cls;
+
+  GNUNET_assert (NULL != cfg);
+  GNUNET_RESOLVER_connect (cfg);
+  tst = GNUNET_NAT_test_start (cfg,
+                              GNUNET_YES,
+                              0, 0,
+                              &result_callback,
+                              ok);
+  if (NULL == tst)
+    {
+      *ok = GNUNET_SYSERR;
+      return;
+    }
+  tsk = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                     &fail_timeout,
+                                     ok);
+}
+
+/**
+ * Test if connection reversal (ICMP method) works.
+ *
+ * @return GNUNET_YES if it works, GNUNET_NO if not.
+ */
+static int
+test_connection_reversal ()
+{
+  int ok;
+  struct GNUNET_OS_Process *resolver;
+
+  resolver = GNUNET_OS_start_process (NULL, NULL,
+                                     "gnunet-service-resolver", 
+                                     "gnunet-service-resolver", NULL);
+  ok = GNUNET_NO;
+  GNUNET_SCHEDULER_run (&reversal_test, &ok);
+  if (NULL != resolver)
+    {
+      GNUNET_break (0 == GNUNET_OS_process_kill (resolver, SIGTERM));
+      GNUNET_OS_process_close (resolver);
+    }
+  return ok;
+}
+
+
+/**
+ * Process list of local IP addresses.  Find and set the
+ * one of the default interface.
+ *
+ * @param cls closure (not used)
+ * @param name name of the interface (can be NULL for unknown)
+ * @param isDefault is this presumably the default interface
+ * @param addr address of this interface (can be NULL for unknown or 
unassigned)
+ * @param addrlen length of the address
+ * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
+ */
+static int
+nipo (void *cls,
+      const char *name,
+      int isDefault,
+      const struct sockaddr *
+      addr, socklen_t addrlen)
+{
+  const struct sockaddr_in *in;
+  char buf[INET_ADDRSTRLEN];
+  GtkEntry *entry;
+
+  if (! isDefault)
+    return GNUNET_OK;
+  if (addrlen != sizeof (struct sockaddr_in))
+    return GNUNET_OK;
+  in = (const struct sockaddr_in*) addr;
+
+  /* set internal IP address */
+  inet_ntop (AF_INET, &in->sin_addr, buf, sizeof(buf));
+  GNUNET_CONFIGURATION_set_value_string (cfg,
+                                        "nat",
+                                        "INTERNAL_ADDRESS",
+                                        buf);
+  entry = GTK_ENTRY (gtk_builder_get_object (builder,
+                                            
"GNUNET_setup_transport_internal_ip_entry"));
+  if (entry == NULL)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+  gtk_entry_set_text (entry,
+                     buf);
+  /* no need to continue iteration */
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * User asked for autoconfiguration.  Try the full program.
+ */
+void
+GNUNET_setup_transport_autoconfig_button_clicked_cb ()
+{
+  struct in_addr ia;
+  char buf[INET_ADDRSTRLEN];
+  GtkEntry *entry;
+  GtkToggleButton *button;
+  int hns;
+  int hnc;
+  char *tmp;
+
+  /* try to detect external IP */
+  if (GNUNET_OK ==
+      GNUNET_NAT_mini_get_external_ipv4 (&ia))
+    {
+      /* enable 'behind nat' */
+      GNUNET_CONFIGURATION_set_value_string (cfg,
+                                            "nat",
+                                            "BEHIND_NAT",
+                                            "YES");
+      button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
+                                                         
"GNUNET_setup_transport_nat_checkbutton"));
+      if (button == NULL)
+       {
+         GNUNET_break (0);
+         return;
+       }
+      gtk_toggle_button_set_active (button,
+                                   TRUE);
+
+      /* set external IP address */
+      inet_ntop (AF_INET, &ia, buf, sizeof(buf));
+      GNUNET_CONFIGURATION_set_value_string (cfg,
+                                            "nat",
+                                            "EXTERNAL_ADDRESS",
+                                            buf);
+      entry = GTK_ENTRY (gtk_builder_get_object (builder,
+                                                
"GNUNET_setup_transport_external_ip_address_entry"));
+      if (entry == NULL)
+       {
+         GNUNET_break (0);
+         return;
+       }
+      gtk_entry_set_text (entry,
+                         buf);     
+    }
+
+  /* Try to detect internal IP */
+  GNUNET_OS_network_interfaces_list (&nipo, NULL);
+
+  /* FIXME: do more: test if UPnP works */
+
+  /* test gnunet-helper-nat-server */
+  tmp = NULL;
+  hns = ( (GNUNET_OK ==
+          GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                 "nat",
+                                                 "EXTERNAL_ADDRESS",
+                                                 &tmp)) &&
+         (0 < strlen (tmp)) &&
+         (GNUNET_YES ==
+          GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                                "nat",
+                                                "BEHIND_NAT")) &&
+         (GNUNET_YES ==
+          GNUNET_OS_check_helper_binary ("gnunet-helper-nat-server")) );
+  GNUNET_free_non_null (tmp);
+  if (hns)    
+    hns = test_connection_reversal ();    
+
+  button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
+                                                     
"GNUNET_setup_transport_icmp_server_enable_checkbutton"));
+  if (button == NULL)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  gtk_toggle_button_set_active (button,
+                               hns ? TRUE : FALSE);
+    
+
+  /* test gnunet-helper-nat-client */
+  tmp = NULL;
+  hnc = ( (GNUNET_OK ==
+          GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                 "nat",
+                                                 "INTERNAL_ADDRESS",
+                                                 &tmp)) &&
+         (0 < strlen (tmp)) &&
+         (GNUNET_YES !=
+          GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                                "nat",
+                                                "BEHIND_NAT")) &&
+         (GNUNET_YES ==
+          GNUNET_OS_check_helper_binary ("gnunet-helper-nat-client")) );
+  GNUNET_free_non_null (tmp);
+  button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
+                                                     
"GNUNET_setup_transport_icmp_client_enable_checkbutton"));
+  if (button == NULL)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  gtk_toggle_button_set_active (button,
+                               hnc ? TRUE : FALSE);
+}
+
+/* end of gnunet-setup-transport.c */

Copied: gnunet-gtk/src/setup/gnunet-setup.c (from rev 16514, 
gnunet-setup/src/gnunet-setup.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup.c                         (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup.c 2011-08-15 14:15:47 UTC (rev 16546)
@@ -0,0 +1,462 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup.c
+ * @brief Main function of gnunet-setup
+ * @author Christian Grothoff
+ */
+#if ENABLE_NLS
+#include <locale.h>
+#endif
+#include "gnunet-setup.h"
+#include "gnunet-setup-options.h"
+#include <regex.h>
+
+/**
+ * Builder for the main window (global!)
+ */
+GtkBuilder *builder; 
+
+/**
+ * Our configuration (global!)
+ */
+struct GNUNET_CONFIGURATION_Handle *cfg;
+
+
+/**
+ * @brief get the path to a specific GNUnet installation directory or,
+ * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory
+ * @author Milan
+ * @return a pointer to the dir path (to be freed by the caller)
+ */
+char *
+GNUNET_GTK_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind);
+
+
+
+/**
+ * Get the name of the directory where all of our package
+ * data is stored ($PREFIX/share/)
+ * 
+ * @return name of the data directory
+ */
+const char *
+GNUNET_GTK_get_data_dir ()
+{
+  static char *dd;
+
+  if (dd == NULL)
+    dd = GNUNET_GTK_installation_get_path (GNUNET_OS_IPK_DATADIR);
+  return dd;
+}
+
+
+/**
+ * Create an initialize a new builder based on the
+ * GNUnet-GTK glade file.
+ *
+ * @param filename name of the resource file to load
+ * @return NULL on error
+ */
+GtkBuilder *
+GNUNET_GTK_get_new_builder (const char *filename)
+{
+  char *glade_path;
+  GtkBuilder *ret;
+  GError *error;
+
+  ret = gtk_builder_new ();
+  gtk_builder_set_translation_domain (ret, "gnunet-gtk");
+  GNUNET_asprintf (&glade_path,
+                  "%s%s",
+                  GNUNET_GTK_get_data_dir (),
+                  filename);
+  error = NULL;
+  if (0 == gtk_builder_add_from_file (ret, glade_path, &error))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to load `%s': %s\n"),
+                 glade_path,
+                 error->message);
+      g_error_free (error);
+      GNUNET_free (glade_path);
+      return NULL;
+    }
+  gtk_builder_connect_signals (ret, NULL);
+  GNUNET_free (glade_path);
+  return ret;
+}
+
+
+
+/**
+ * Initialize GNU gettext for message translation.
+ */
+static void
+setup_nls ()
+{
+#if ENABLE_NLS
+  char *path;
+
+  setlocale (LC_ALL, "");
+  GNUNET_asprintf (&path,
+                  "%s/%s/locale/",
+                  GNUNET_GTK_get_data_dir (),
+                  PACKAGE_NAME);
+  bindtextdomain ("gnunet-setup", path);
+  textdomain ("gnunet-setup");
+  bind_textdomain_codeset ("GNUnet", "UTF-8");
+  bind_textdomain_codeset ("gnunet-setup", "UTF-8");
+  GNUNET_free (path);
+#else
+  fprintf (stderr,
+          "WARNING: gnunet-setup was compiled without i18n support (did CFLAGS 
contain -Werror?).\n");
+#endif
+}
+
+
+/**
+ * Initialize GTK search path for icons.
+ */
+static void
+set_icon_search_path ()
+{
+  char *buf;
+
+  buf = GNUNET_GTK_installation_get_path (GNUNET_OS_IPK_ICONDIR);
+  gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), buf);
+  GNUNET_free (buf);
+}
+
+
+static gboolean
+help_click_callback (GtkWidget *widget,
+                    GdkEventButton *event,
+                    gpointer user_data)
+{
+  const struct GNUNET_SETUP_OptionSpecification *os = user_data;
+  GtkLinkButton *help;
+
+  if (event->type != GDK_BUTTON_PRESS)
+    return FALSE;
+  help = GTK_LINK_BUTTON (gtk_builder_get_object (builder, 
+                                                 "GNUNET_setup_help_text"));
+  gtk_link_button_set_uri (help, 
+                          os->help_url);
+  gtk_button_set_label (GTK_BUTTON (help),
+                       os->help_text);  
+  return FALSE;
+}
+
+
+/**
+ * Change the visibility of widgets according to the 
+ * value and visibility specification given.
+ *
+ * @param os option specification
+ * @param value current value for the given option
+ */
+static void
+update_visibility (const struct GNUNET_SETUP_OptionSpecification *os,
+                  const char *value)
+{
+  unsigned int i;
+  const struct GNUNET_SETUP_VisibilitySpecification *vs;
+  GtkWidget *widget;
+  regex_t r;
+
+  if (os->visibility == NULL)
+    return;
+  i = 0;
+  while (os->visibility[i].widget_name != NULL)
+    {
+      vs = &os->visibility[i];
+      widget = GTK_WIDGET (gtk_builder_get_object (builder, 
+                                                  vs->widget_name));
+      if (widget == NULL)
+       {
+         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                     _("Widget `%s' not found\n"),
+                     vs->widget_name);
+       }      
+      if (NULL != vs->show_value)
+       {
+         if (0 != regcomp (&r, vs->show_value, REG_EXTENDED | REG_ICASE | 
REG_NOSUB))
+           {
+             GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                         _("Invalid regular expression `%s'\n"),
+                         vs->show_value);
+             i++;
+             continue;
+           }
+         if (0 == regexec (&r, value, 0, NULL, 0))
+           gtk_widget_show (widget);
+         else
+           gtk_widget_hide (widget);       
+         regfree (&r);
+       }
+      if (NULL != vs->hide_value)
+       {
+         if (0 != regcomp (&r, vs->hide_value, REG_ICASE | REG_NOSUB))
+           {
+             GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                         _("Invalid regular expression `%s'\n"),
+                         vs->show_value);
+             i++;
+             continue;
+           }
+         if (0 == regexec (&r, value, 0, NULL, 0))
+           gtk_widget_hide (widget);
+         else
+           gtk_widget_show (widget);
+         regfree (&r);
+       }
+      i++;
+    }
+}
+                  
+
+/**
+ * Function called whenever a widget changes its state.
+ */
+static void
+widget_state_change_callback (const struct GNUNET_SETUP_OptionSpecification 
*os)
+{
+  GObject *widget;
+  char *value;
+
+  widget = gtk_builder_get_object (builder,
+                                  os->widget_name);
+  GNUNET_assert (NULL != os->save_function);
+  if (GNUNET_OK !=
+      os->save_function (os->load_save_cls,
+                        os->section,
+                        os->option,
+                        widget,
+                        cfg))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Failed to obtain option value from widget `%s'\n"),
+                 os->widget_name);
+      return;
+    }
+  if ( (os->section != NULL) &&
+       (os->option != NULL) )
+    GNUNET_assert (GNUNET_OK ==
+                  GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                         os->section,
+                                                         os->option,
+                                                         &value));
+  else
+    value = NULL;
+  update_visibility (os, value);
+  GNUNET_free_non_null (value);
+}
+
+
+int
+main (int argc,
+      char *const *argv)
+{
+  char *cfgName = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
+  char *loglev = GNUNET_strdup ("WARNING");
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_CFG_FILE (&cfgName),
+    GNUNET_GETOPT_OPTION_HELP (gettext_noop ("Setup tool for GNUnet")),
+    GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
+    GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION),
+    GNUNET_GETOPT_OPTION_END
+  };
+  gint ret;
+  GtkWidget *main_window;
+  GtkWidget *dialog;
+  GObject *widget;
+  int arg_off;
+  int iret;
+  char *const *argp;
+  char *value;
+  struct GNUNET_CONFIGURATION_Handle *cfgDefault;
+  const struct GNUNET_SETUP_OptionSpecification *os;
+  unsigned int i;
+ 
+  arg_off = GNUNET_GETOPT_run ("gnunet-setup",
+                              options,
+                              argc,
+                              argv);  
+  if (arg_off == GNUNET_SYSERR)
+    {
+      GNUNET_free (loglev);
+      GNUNET_free (cfgName);
+      return 1;
+    }
+  (void) GNUNET_log_setup ("gnunet-setup",
+                          loglev,
+                          NULL);
+  argp = &argv[arg_off];
+  argc -= arg_off;
+  gtk_init (&argc, (char ***) &argp);
+  set_icon_search_path ();
+  setup_nls ();
+  builder = GNUNET_GTK_get_new_builder ("gnunet-setup.glade");
+  if (builder == NULL)
+    {
+      GNUNET_free (loglev);
+      GNUNET_free (cfgName);
+      return 1;        
+    }
+  cfg = GNUNET_CONFIGURATION_create ();
+  (void) GNUNET_CONFIGURATION_load (cfg, cfgName);
+  main_window = GTK_WIDGET (gtk_builder_get_object (builder, 
+                                                   "GNUNET_setup_dialog"));
+  /* load options into dialog */
+  i = 0;
+  while (option_specifications[i].widget_name != NULL)
+    {
+      os = &option_specifications[i];
+      widget = gtk_builder_get_object (builder,
+                                      os->widget_name);
+      if (NULL == widget)
+       {
+         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                     _("Widget `%s' not found\n"),
+                     os->widget_name);
+         i++;
+         continue;
+       }
+      if (os->load_function != NULL) 
+       {
+         if ( (NULL == os->section) || 
+              (NULL == os->option) )
+           {
+             if (GNUNET_OK != 
+                 os->load_function (os->load_save_cls,
+                                    NULL, NULL, NULL,
+                                    widget,
+                                    cfg)) 
+               {
+                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                             _("Failed to initialize widget `%s'\n"),
+                             os->widget_name);
+               }
+           }
+         else
+           {
+             if (GNUNET_OK !=
+                 GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                        os->section,
+                                                        os->option,
+                                                        &value))
+               {
+                 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                             _("No default value known for option `%s' in 
section `%s'\n"),
+                             os->option,
+                             os->section);
+               }
+             else
+               {
+                 if (GNUNET_OK != 
+                     os->load_function (os->load_save_cls,
+                                        os->section, os->option,
+                                        value,
+                                        widget,
+                                        cfg)) 
+                   {
+                     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                                 _("Failed to initialize widget `%s' with 
value `%s'\n"),
+                                 os->widget_name,
+                                 value);
+                   }
+                 else
+                   {
+                     update_visibility (os, value);
+                   }
+                 GNUNET_free (value);
+               }
+           }
+       }
+      if (os->help_text != NULL)
+       {
+         g_signal_connect (widget,
+                           "button-press-event",
+                           G_CALLBACK (&help_click_callback),
+                           (void*) os);
+       }
+      if (os->change_signal != NULL)
+       {
+         GNUNET_assert (NULL != os->save_function);
+         g_signal_connect_swapped (widget,
+                                   os->change_signal,
+                                   G_CALLBACK (&widget_state_change_callback),
+                                   (void*) os);            
+       }
+      i++;
+    }
+
+ RESTART:
+  ret = gtk_dialog_run (GTK_DIALOG (main_window));
+  gtk_widget_hide (main_window);
+  cfgDefault = GNUNET_CONFIGURATION_create ();
+  (void) GNUNET_CONFIGURATION_load (cfgDefault, NULL); /* load defaults only */
+  iret = 0;
+  switch (ret)
+    {
+    case GTK_RESPONSE_CANCEL: /* -6 */
+      /* explicit cancel, do not save! */
+      break;
+    case GTK_RESPONSE_OK: /* save-as, -5 */
+      dialog = gtk_file_chooser_dialog_new (_("Save Configuration File"),
+                                           NULL,
+                                           GTK_FILE_CHOOSER_ACTION_SAVE,
+                                           GTK_STOCK_CANCEL, 
GTK_RESPONSE_CANCEL,
+                                           GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                           NULL);
+      gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), cfgName);
+      if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT)
+       {
+         gtk_widget_destroy (dialog);
+         goto RESTART;
+       }
+      GNUNET_free (cfgName);
+      cfgName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+      gtk_widget_destroy (dialog);
+      /* fall through! */
+    case GTK_RESPONSE_DELETE_EVENT: /* window close, -4 */
+    case GTK_RESPONSE_ACCEPT: /* save, -3 */
+      if (GNUNET_OK !=
+         GNUNET_CONFIGURATION_write_diffs (cfgDefault,
+                                           cfg,
+                                           cfgName))
+       iret = 1;
+      break;
+    default:
+      GNUNET_break (0);
+    }
+  gtk_widget_destroy (main_window);
+  g_object_unref (G_OBJECT (builder));  
+  GNUNET_CONFIGURATION_destroy (cfgDefault);
+  GNUNET_CONFIGURATION_destroy (cfg);
+  GNUNET_free (cfgName);
+  GNUNET_free (loglev);
+  return iret;
+}
+
+
+/* end of gnunet-setup.c */

Copied: gnunet-gtk/src/setup/gnunet-setup.h (from rev 16514, 
gnunet-setup/src/gnunet-setup.h)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup.h                         (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup.h 2011-08-15 14:15:47 UTC (rev 16546)
@@ -0,0 +1,47 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/gnunet-setup.h
+ * @brief globals
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_SETUP_H
+#define GNUNET_SETUP_H
+
+#include "gnunet_gtk.h"
+#include <gnunet/gnunet_directories.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <gladeui/glade.h>
+#include <gtk/gtk.h>
+
+/**
+ * Builder for the main window.
+ */
+extern GtkBuilder *builder; 
+
+/**
+ * Our configuration.
+ */
+extern struct GNUNET_CONFIGURATION_Handle *cfg;
+
+
+#endif
+/* end of gnunet-setup.h */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]