gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r22229 - in gnunet-gtk: contrib src/setup


From: gnunet
Subject: [GNUnet-SVN] r22229 - in gnunet-gtk: contrib src/setup
Date: Sat, 23 Jun 2012 20:57:21 +0200

Author: grothoff
Date: 2012-06-23 20:57:21 +0200 (Sat, 23 Jun 2012)
New Revision: 22229

Added:
   gnunet-gtk/src/setup/gnunet-setup-dns-exit.c
   gnunet-gtk/src/setup/gnunet-setup-gns.c
   gnunet-gtk/src/setup/gnunet-setup-namestore-config.c
   gnunet-gtk/src/setup/gnunet-setup-namestore-plugins.c
Modified:
   gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade
   gnunet-gtk/src/setup/Makefile.am
   gnunet-gtk/src/setup/gnunet-setup-options.c
   gnunet-gtk/src/setup/gnunet-setup.c
   gnunet-gtk/src/setup/gnunet-setup.h
Log:
-adding tab for namespace database configuration to namestore

Modified: gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade       2012-06-23 
18:50:13 UTC (rev 22228)
+++ gnunet-gtk/contrib/gnunet_setup_gtk_main_window.glade       2012-06-23 
18:57:21 UTC (rev 22229)
@@ -4154,6 +4154,264 @@
               </packing>
             </child>
             <child>
+              <object class="GtkVBox" id="GNUNET_setup_namestore_vbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkFrame" id="GNUNET_setup_namestore_frame">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" 
id="GNUNET_setup_namestore_alignment">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkVBox" 
id="GNUNET_setup_namestore_vbox1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <child>
+                              <object class="GtkHBox" 
id="GNUNET_setup_namestore_hbox">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkLabel" 
id="GNUNET_setup_namestore_label1">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" 
translatable="yes">Database Backend to use:</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="padding">5</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkHButtonBox" 
id="GNUNET_setup_namestore_hbuttonbox">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property 
name="layout_style">start</property>
+                                    <child>
+                                      <object class="GtkRadioButton" 
id="GNUNET_setup_namestore_sqlite_radiobutton">
+                                        <property name="label" 
translatable="yes">sqLite</property>
+                                        <property 
name="use_action_appearance">False</property>
+                                        <property 
name="visible">True</property>
+                                        <property 
name="can_focus">True</property>
+                                        <property 
name="receives_default">False</property>
+                                        <property name="xalign">0</property>
+                                        <property name="active">True</property>
+                                        <property 
name="draw_indicator">True</property>
+                                        <signal name="toggled" 
handler="GNUNET_setup_namestore_sqlite_radiobutton_toggled_cb" swapped="no"/>
+                                        <signal name="realize" 
handler="GNUNET_setup_namestore_sqlite_radiobutton_realize_cb" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property 
name="expand">False</property>
+                                        <property name="fill">False</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkRadioButton" 
id="GNUNET_setup_namestore_postgres_radiobutton">
+                                        <property name="label" 
translatable="yes">Postgres</property>
+                                        <property 
name="use_action_appearance">False</property>
+                                        <property 
name="visible">True</property>
+                                        <property 
name="can_focus">True</property>
+                                        <property 
name="receives_default">False</property>
+                                        <property name="xalign">0</property>
+                                        <property 
name="draw_indicator">True</property>
+                                        <property 
name="group">GNUNET_setup_namestore_sqlite_radiobutton</property>
+                                        <signal name="toggled" 
handler="GNUNET_setup_namestore_postgres_radiobutton_toggled_cb" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property 
name="expand">False</property>
+                                        <property name="fill">False</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkNotebook" 
id="GNUNET_setup_namestore_notebook">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <child>
+                                  <object class="GtkLabel" 
id="GNUNET_setup_namestore_sqlite_label">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" 
translatable="yes">No setup required.</property>
+                                  </object>
+                                </child>
+                                <child type="tab">
+                                  <object class="GtkLabel" 
id="GNUNET_setup_namestore_sqlite_tab_label">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" 
translatable="yes">sqLite</property>
+                                  </object>
+                                  <packing>
+                                    <property name="tab_fill">False</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkHBox" 
id="GNUNET_setup_namestore_postgres_hbox">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel" 
id="GNUNET_setup_namestore_postgres_config_label">
+                                        <property 
name="visible">True</property>
+                                        <property 
name="can_focus">False</property>
+                                        <property name="label" 
translatable="yes">Configuration:</property>
+                                      </object>
+                                      <packing>
+                                        <property 
name="expand">False</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkEntry" 
id="GNUNET_setup_namestore_postgres_config_entry">
+                                        <property 
name="visible">True</property>
+                                        <property 
name="can_focus">True</property>
+                                        <property 
name="invisible_char">•</property>
+                                        <property 
name="invisible_char_set">True</property>
+                                        <property 
name="primary_icon_activatable">False</property>
+                                        <property 
name="secondary_icon_activatable">False</property>
+                                        <property 
name="primary_icon_sensitive">True</property>
+                                        <property 
name="secondary_icon_sensitive">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child type="tab">
+                                  <object class="GtkHBox" 
id="GNUNET_setup_namestore_postgres_tab_hbox ">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <child>
+                                      <object class="GtkLabel" 
id="GNUNET_setup_namestore_postgres_tab_label">
+                                        <property 
name="visible">True</property>
+                                        <property 
name="can_focus">False</property>
+                                        <property name="label" 
translatable="yes">Postgres</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkButton" 
id="GNUNET_setup_namestore_postgres_tab_test_button">
+                                        <property name="label" 
translatable="yes">Test configuration</property>
+                                        <property 
name="use_action_appearance">False</property>
+                                        <property 
name="visible">True</property>
+                                        <property 
name="can_focus">True</property>
+                                        <property 
name="receives_default">True</property>
+                                        <signal name="clicked" 
handler="GNUNET_setup_namestore_postgres_tab_test_button_clicked_cb" 
swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="padding">5</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkImage" 
id="GNUNET_setup_namestore_postgres_tab_ok_image">
+                                        <property 
name="can_focus">False</property>
+                                        <property name="tooltip_text" 
translatable="yes">Configuration works!</property>
+                                        <property 
name="pixbuf">gnunet-setup-oxygen-ok.png</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkImage" 
id="GNUNET_setup_namestore_postgres_tab_error_image">
+                                        <property 
name="can_focus">False</property>
+                                        <property name="tooltip_text" 
translatable="yes">Configuration error!</property>
+                                        <property 
name="pixbuf">gnunet-setup-oxygen-cancel.png</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                    <property name="tab_fill">False</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" 
id="GNUNET_setup_namestore_frame_label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" 
translatable="yes">&lt;b&gt;Configure Namestore (persistent 
storage)&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">6</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="GNUNET_setup_namestore_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" 
translatable="yes">N_amsestore</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="position">6</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkVBox" id="GNUNET_setup_gns_vbox">
                 <property name="can_focus">False</property>
                 <child>
@@ -4337,7 +4595,6 @@
                             <child>
                               <object class="GtkCellRendererCombo" 
id="GNUNET_setup_gns_type_cellrenderercombo">
                                 <property name="editable">True</property>
-                                <property name="model"></property>
                                 <property name="text_column">1</property>
                               </object>
                               <attributes>
@@ -4396,7 +4653,7 @@
                 </child>
               </object>
               <packing>
-                <property name="position">6</property>
+                <property name="position">7</property>
                 <property name="tab_fill">False</property>
               </packing>
             </child>
@@ -4408,7 +4665,7 @@
                 <property name="use_underline">True</property>
               </object>
               <packing>
-                <property name="position">6</property>
+                <property name="position">7</property>
                 <property name="tab_fill">False</property>
               </packing>
             </child>

Modified: gnunet-gtk/src/setup/Makefile.am
===================================================================
--- gnunet-gtk/src/setup/Makefile.am    2012-06-23 18:50:13 UTC (rev 22228)
+++ gnunet-gtk/src/setup/Makefile.am    2012-06-23 18:57:21 UTC (rev 22229)
@@ -27,6 +27,8 @@
   gnunet-setup-datastore-config.c \
   gnunet-setup-datacache-plugins.c \
   gnunet-setup-datacache-config.c \
+  gnunet-setup-namestore-plugins.c \
+  gnunet-setup-namestore-config.c \
   gnunet-setup-hostlist-editing.c \
   gnunet-setup-hostlist-server.c 
 gnunet_setup_LDADD = \

Added: gnunet-gtk/src/setup/gnunet-setup-dns-exit.c
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-dns-exit.c                                
(rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-dns-exit.c        2012-06-23 18:57:21 UTC 
(rev 22229)
@@ -0,0 +1,749 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2011, 2012 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/setup/gnunet-setup-dns-exit.c
+ * @brief code for the dialog to configure GNS-EXIT records
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gdk/gdkkeysyms.h>
+
+
+/**
+ * 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,
+                                       GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, "",
+                                       GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT,
+                                       (guint) 80,
+                                       GNUNET_GTK_SETUP_GNS_MC_TARGETPORT,
+                                       (guint) 8080,
+                                       GNUNET_GTK_SETUP_GNS_MC_HOSTNAME,
+                                       "localhost4",
+                                       GNUNET_GTK_SETUP_GNS_MC_ISUDP, "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,
+                                           GNUNET_GTK_SETUP_GNS_MC_HOSTNAME,
+                                           sld,
+                                           GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT,
+                                           (guint) local_port,
+                                           GNUNET_GTK_SETUP_GNS_MC_TARGETPORT,
+                                           (guint) host_port,
+                                           
GNUNET_GTK_SETUP_GNS_MC_TARGETHOSTNAME,
+                                           hostname,
+                                           GNUNET_GTK_SETUP_GNS_MC_ISUDP,
+                                           (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,
+                          GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, &hostname,
+                          GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT, &srcport,
+                          GNUNET_GTK_SETUP_GNS_MC_TARGETPORT, &targetport,
+                          GNUNET_GTK_SETUP_GNS_MC_TARGETHOSTNAME, &targethost,
+                          GNUNET_GTK_SETUP_GNS_MC_ISUDP, &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);
+    if ((strlen (pos->udpred) > 0) || (strlen (pos->tcpred) > 0))
+      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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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, GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, &old, -1);
+  if ((0 != strlen (old)) && (0 == strlen (new_text)))
+  {
+    /* deletion */
+    gtk_list_store_remove (ls, &iter);
+    g_free (old);
+    /* update configuration */
+    update_vpn_dns_configuration (tm);
+    return;
+  }
+  /* update model */
+  gtk_list_store_set (ls, &iter,
+                      GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, 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
+gns_name_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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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, GNUNET_GTK_SETUP_GNS_MC_ISUDP, 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
+gns_type_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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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,
+                      GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT, (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
+gns_ttl_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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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,
+                      GNUNET_GTK_SETUP_GNS_MC_TARGETHOSTNAME, 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
+gns_value_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;
+}
+
+
+#if 0
+  {
+   "GNUNET_setup_gns_treeview",
+   NULL,
+   NULL,
+   NULL,
+   gettext_noop
+   ("Specification of .gnunet TLD"),
+   "https://gnunet.org/configuration-dns";,
+   &load_vpn_dns_configuration,
+   NULL, NULL,
+   NULL, NULL,
+   NULL},
+
+  {
+   "GNUNET_setup_gns_name_cellrenderertext",
+   "editing-started",
+   NULL,
+   NULL,
+   NULL,
+   "https://gnunet.org/configuration-dns";,
+   NULL,
+   &gns_name_install_edited_handler,
+   NULL,
+   NULL,
+   NULL,
+   NULL},
+
+  {
+   "GNUNET_setup_gns_type_cellrenderertext",
+   "editing-started",
+   NULL,
+   NULL,
+   NULL,
+   "https://gnunet.org/configuration-dns";,
+   NULL,
+   &gns_type_install_edited_handler,
+   NULL,
+   NULL,
+   NULL,
+   NULL},
+
+  {
+   "GNUNET_setup_gns_ttl_cellrenderertext",
+   "editing-started",
+   NULL,
+   NULL,
+   NULL,
+   "https://gnunet.org/configuration-dns";,
+   NULL,
+   &gns_ttl_install_edited_handler,
+   NULL,
+   NULL,
+   NULL,
+   NULL},
+
+  {
+   "GNUNET_setup_gns_value_cellrenderertext",
+   "editing-started",
+   NULL,
+   NULL,
+   NULL,
+   "https://gnunet.org/configuration-dns";,
+   NULL,
+   &gns_value_install_edited_handler,
+   NULL,
+   NULL,
+   NULL,
+   NULL},
+
+#endif
+
+/* end of gnunet-setup-dns-exit.c */

Copied: gnunet-gtk/src/setup/gnunet-setup-gns.c (from rev 22226, 
gnunet-gtk/src/gns/gnunet-gns-gtk_zone.c)
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-gns.c                             (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-gns.c     2012-06-23 18:57:21 UTC (rev 
22229)
@@ -0,0 +1,1718 @@
+/*
+     This file is part of GNUnet
+     (C) 2012 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/setup/gnunet-setup-gns.c
+ * @author Christian Grothoff
+ * @brief everything releated to the main GNS zone tree view
+ */
+#include "gnunet_gtk.h"
+#include "gnunet-gns-gtk.h"
+
+
+/**
+ * Columns in the gns model.
+ */
+enum GNSTreestoreColumn
+{
+  /**
+   * A gchararray
+   */
+  GNS_TREESTORE_COL_NAME = 0,
+
+  /**
+   * A gboolean
+   */
+  GNS_TREESTORE_COL_IS_PUBLIC,
+
+  /**
+   * A guint
+   */
+  GNS_TREESTORE_COL_RECORD_TYPE,
+
+  /**
+   * A gchararray
+   */
+  GNS_TREESTORE_COL_RECORD_TYPE_AS_STR,
+
+  /**
+   * A guint64
+   */
+  GNS_TREESTORE_COL_EXP_TIME,
+
+  /**
+   * A gboolean
+   */
+  GNS_TREESTORE_COL_EXP_TIME_IS_REL,
+
+  /**
+   * A gchararray
+   */
+  GNS_TREESTORE_COL_EXP_TIME_AS_STR,
+
+  /**
+   * A gchararray
+   */
+  GNS_TREESTORE_COL_VAL_AS_STR,
+
+  /**
+   * A gchararray
+   */
+  GNS_TREESTORE_COL_VAL_COLOR,
+
+  /**
+   * A gboolean
+   */
+  GNS_TREESTORE_COL_NAME_IS_VISIBLE,
+
+  /**
+   * A gboolean
+   */
+  GNS_TREESTORE_COL_IS_RECORD_ROW,
+
+  /**
+   * A gboolean
+   */
+  GNS_TREESTORE_COL_NOT_DUMMY_ROW,
+
+  /**
+   * A gchararray
+   */
+  GNS_TREESTORE_COL_EXP_TIME_COLOR,
+
+  /**
+   * A gchararray
+   */
+  GNS_TREESTORE_COL_NAME_COLOR
+};
+
+
+/**
+ * Columns in the gns type model.
+ */
+enum LIST_COLUMNS
+{
+
+  /**
+   * A guint
+   */
+  GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPE = 0,
+
+
+  /**
+   * A gchararray
+   */
+  GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPENAME
+};
+
+
+/**
+ *
+ */
+struct UpdateContext
+{
+  /**
+   *
+   */
+  struct GNUNET_GNS_Context *gns;
+
+  /**
+   *
+   */
+  struct GNUNET_NAMESTORE_RecordData *rd;
+
+  /**
+   *
+   */
+  char * name;
+
+  /**
+   *
+   */
+  unsigned int rd_count;
+};
+
+
+/**
+ * Name of our zone as a string.
+ */
+static char *zone_as_string;
+
+/**
+ * Default directory of zone files as a string.
+ */
+static char *zonekey_directory;
+
+
+struct GNUNET_GNS_Context
+{
+  /**
+   * Handle to the namestore.
+   */
+  struct GNUNET_NAMESTORE_Handle *ns;
+
+  GtkCheckMenuItem *shorten_menu;
+
+  GtkTreeStore *ts;
+  GtkListStore *ls;
+  GtkTreeModel *tm;
+  GtkTreeView *tv;
+
+  struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
+  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
+
+  struct GNUNET_CRYPTO_ShortHashCode zone;
+  int iteration;
+};
+
+
+static void
+check_name_validity_and_commit_remove_proc (void *cls,
+                                            int32_t success,
+                                            const char *emsg)
+{
+  struct UpdateContext * uc = cls;
+  unsigned int c;
+  if ((GNUNET_OK == success) || (GNUNET_NO == success))
+  {
+     for (c = 0; c < uc->rd_count; c++)
+     {
+       GNUNET_NAMESTORE_record_create(uc->gns->ns, uc->gns->pkey,
+           uc->name, &uc->rd[c],NULL, NULL);
+       GNUNET_free ((void *) uc->rd[c].data);
+     }
+     GNUNET_free (uc->rd);
+     GNUNET_free (uc->name);
+     GNUNET_free (uc);
+  }
+  else if (GNUNET_SYSERR == success)
+  {
+    for (c = 0; c < uc->rd_count; c++)
+      GNUNET_free ((void *) uc->rd[c].data);
+    GNUNET_free (uc->rd);
+    GNUNET_free (uc->name);
+    GNUNET_free (uc);
+  }
+  else
+  {
+    GNUNET_break (0);
+    GNUNET_free (uc);
+  }
+}
+
+
+static void
+check_name_validity_and_commit (struct GNUNET_GNS_Context *gns, gchar *path, 
char * oldname)
+{
+  GtkTreeIter it;
+  GtkTreeIter parent;
+  int records;
+  int children;
+  int append_pseu;
+  int c;
+  int valid = GNUNET_YES;
+  char * name;
+  void * data;
+  size_t data_size;
+  const gchar * pseu;
+
+  char          *n_name;
+  int           n_type;
+  gboolean      n_public;
+  char          *n_exp_color;
+  guint64       n_exp_time;
+  char          *n_exp_str;
+  gboolean      n_is_relative;
+  char          *n_value;
+  char          *n_value_color;
+
+
+  gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
+
+  if (FALSE == gtk_tree_model_iter_parent (gns->tm, &parent, &it))
+    parent = it;
+
+  children = gtk_tree_model_iter_n_children (gns->tm, &parent);
+  if (children < 1)
+  {
+    return;
+  }
+
+  gtk_tree_model_get(gns->tm, &parent,
+                     GNS_TREESTORE_COL_NAME, &name,
+                     -1);
+
+  if (0 == strcmp (name, ROOT_STR))
+  {
+    /* We have to append PSEU RECORD */
+    append_pseu = GNUNET_YES;
+    records = children + 1;
+  }
+  else
+  {
+    append_pseu = GNUNET_NO;
+    records = children;
+  }
+
+  struct GNUNET_NAMESTORE_RecordData *rd = GNUNET_malloc (records * sizeof 
(struct GNUNET_NAMESTORE_RecordData));
+
+  if (FALSE == gtk_tree_model_iter_children (gns->tm, &it, &parent))
+    return;
+
+  for (c = 0; c < children; c++)
+  {
+    gtk_tree_model_get(gns->tm, &it,
+                       GNS_TREESTORE_COL_NAME, &n_name,
+                       GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
+                       GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
+                       GNS_TREESTORE_COL_EXP_TIME_COLOR, &n_exp_color,
+                       GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
+                       GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative,
+                       GNS_TREESTORE_COL_EXP_TIME_AS_STR, &n_exp_str,
+                       GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
+                       GNS_TREESTORE_COL_VAL_COLOR, &n_value_color,
+                       -1);
+    /* valid name */
+    if (NULL == n_name)
+      valid = GNUNET_NO;
+    else
+    {
+      if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (n_name))
+      valid = GNUNET_NO;
+    }
+
+    /* valid record type */
+    if (0 == n_type)
+      valid = GNUNET_NO;
+
+    /* valid expiration */
+    if ((n_exp_color != NULL) || (NULL == n_exp_str) || (0 == n_exp_time))
+        valid = GNUNET_NO;
+
+    /* valid value */
+    if ((n_value_color != NULL) || (NULL == n_value))
+        valid = GNUNET_NO;
+    if (NULL != n_value)
+    {
+      if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value(n_type, n_value, 
&data, &data_size))
+        valid = GNUNET_NO;
+    }
+
+    if (GNUNET_YES == valid)
+    {
+      if (FALSE == n_public)
+        rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | 
GNUNET_NAMESTORE_RF_PRIVATE;
+      else
+        rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
+      rd[c].record_type = n_type;
+      rd[c].expiration_time = n_exp_time;
+      rd[c].data_size = data_size;
+      rd[c].data = GNUNET_malloc(data_size);
+      memcpy ((void *) rd[c].data, data, data_size);
+    }
+    g_free (n_name);
+    g_free (n_exp_color);
+    g_free (n_exp_str);
+    g_free (n_value);
+    g_free (n_value_color);
+
+    if (FALSE == gtk_tree_model_iter_next (gns->tm, &it))
+      break;
+  }
+
+  if (GNUNET_NO == valid)
+  {
+    for (c = 0; c < children; c++)
+      GNUNET_free_non_null ((void *)  rd[c].data);
+    GNUNET_free_non_null (rd);
+  }
+  else
+  {
+
+    if (GNUNET_YES == append_pseu)
+    {
+      GNUNET_assert (children == (records -1));
+
+      /* Append PSEU record */
+      GtkEntry * entry = GTK_ENTRY (gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_pseu_entry"));
+      pseu = gtk_entry_get_text (GTK_ENTRY(entry));
+      if ((NULL != pseu) && (0 != strcmp (PSEU_EMPTY_STR, pseu)) && (0 != 
strcmp ("", pseu)))
+      {
+        if (GNUNET_OK != 
GNUNET_NAMESTORE_string_to_value(GNUNET_NAMESTORE_TYPE_PSEU,
+                                  pseu,
+                                  (void **) &rd[records - 1].data,
+                                  &rd[records - 1].data_size))
+        {
+          GNUNET_break (0);
+          for (c = 0; c < records; c++)
+            GNUNET_free_non_null ((void *) rd[c].data);
+          GNUNET_free_non_null (rd);
+        }
+        rd[records - 1].record_type = GNUNET_NAMESTORE_TYPE_PSEU;
+        rd[records - 1].expiration_time = UINT64_MAX;
+        rd[records - 1].flags = GNUNET_NAMESTORE_RF_AUTHORITY | 
GNUNET_NAMESTORE_RF_NONE;
+      }
+      else
+      {
+        GNUNET_break (0);
+      }
+    }
+
+    /* Remove old entries */
+    struct UpdateContext * uc = GNUNET_malloc (sizeof (struct UpdateContext));
+    uc->gns = gns;
+    uc->rd = rd;
+    uc->rd_count = records;
+    uc->name = strdup (name);
+    if (oldname != NULL)
+      GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, oldname, NULL, 
&check_name_validity_and_commit_remove_proc, uc);
+    else
+      GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, NULL, 
&check_name_validity_and_commit_remove_proc, uc);
+    g_free (name);
+  }
+}
+
+
+/**
+ *
+ */
+struct Remove_Context
+{
+
+  /**
+   *
+   */
+  struct GNUNET_GNS_Context *gns;
+
+  /**
+   *
+   */
+  char *path;
+};
+
+
+static void
+check_name_validity_and_remove_proc (void *cls,
+                                    int32_t success,
+                                    const char *emsg)
+{
+  struct Remove_Context *rcc = cls;
+  GtkDialog *dialog;
+  GtkTreeIter it;
+  if (GNUNET_SYSERR == success)
+  {
+    char * message = _("Record could not be deleted:");
+    dialog = GTK_DIALOG(gtk_message_dialog_new (GTK_WINDOW 
(rcc->gns->main_window),
+                                     GTK_DIALOG_DESTROY_WITH_PARENT,
+                                     GTK_MESSAGE_ERROR,
+                                     GTK_BUTTONS_CLOSE,
+                                     _("%s\n%s\n"),
+                                     message,
+                                     emsg));
+
+    g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), 
rcc->gns);
+    gtk_widget_show_all (GTK_WIDGET(dialog));
+  }
+  else
+  {
+    gtk_tree_model_get_iter_from_string(rcc->gns->tm, &it, rcc->path);
+    gtk_tree_store_remove (rcc->gns->ts, &it);
+  }
+  GNUNET_free (rcc->path);
+  GNUNET_free (rcc);
+}
+
+
+static void
+check_name_validity_and_remove (struct GNUNET_GNS_Context *gns, gchar *path)
+{
+  GtkTreeIter it;
+  GtkTreeIter parent;
+  char *name;
+  int valid = GNUNET_YES;
+  struct GNUNET_NAMESTORE_RecordData rd;
+  struct Remove_Context *rcc;
+
+  char          *n_name;
+  int           n_type;
+  gboolean      n_public;
+  char          *n_exp_color;
+  guint64       n_exp_time;
+  char          *n_exp_str;
+  gboolean      n_is_relative;
+  char          *n_value;
+  char          *n_value_color;
+
+  gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
+  gtk_tree_model_get(gns->tm, &it,
+                     GNS_TREESTORE_COL_NAME, &name,
+                     -1);
+
+  if (TRUE == gtk_tree_model_iter_parent (gns->tm, &parent, &it))
+  {
+    /* Removing a single record */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        "Removing single record for name `%s'\n", name);
+
+    gtk_tree_model_get(gns->tm, &it,
+                       GNS_TREESTORE_COL_NAME, &n_name,
+                       GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
+                       GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
+                       GNS_TREESTORE_COL_EXP_TIME_COLOR, &n_exp_color,
+                       GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
+                       GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative,
+                       GNS_TREESTORE_COL_EXP_TIME_AS_STR, &n_exp_str,
+                       GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
+                       GNS_TREESTORE_COL_VAL_COLOR, &n_value_color,
+                       -1);
+
+    /* valid name */
+    if (NULL == n_name)
+        valid = GNUNET_NO;
+
+    /* valid record type */
+    if (0 == n_type)
+      valid = GNUNET_NO;
+
+    /* valid expiration */
+    if ((n_exp_color != NULL) || (NULL == n_exp_str) || (0 == n_exp_time))
+        valid = GNUNET_NO;
+
+    /* valid value */
+    if ((n_value_color != NULL) || (NULL == n_value))
+        valid = GNUNET_NO;
+
+    if (GNUNET_YES == valid)
+    {
+      if (FALSE == n_public)
+        rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE;
+      else
+        rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
+      rd.record_type = n_type;
+      rd.expiration_time = n_exp_time;
+      rd.data_size = strlen (n_value) + 1;
+      rd.data = GNUNET_malloc(rd.data_size);
+      memcpy ((void *) rd.data, n_value, rd.data_size);
+
+      rcc = GNUNET_malloc(sizeof (struct Remove_Context));
+      rcc->gns = gns;
+      rcc->path = strdup (path);
+      GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, &rd, 
&check_name_validity_and_remove_proc, rcc);
+      GNUNET_free ((void *) rd.data);
+    }
+    else
+    {
+      gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
+      gtk_tree_store_remove (gns->ts, &it);
+    }
+    g_free (n_name);
+    g_free (n_exp_color);
+    g_free (n_exp_str);
+    g_free (n_value);
+    g_free (n_value_color);
+  }
+  else if (0 != strcmp (name, ROOT_STR))
+  {
+    /* Removing the whole name record */
+    rcc = GNUNET_malloc(sizeof (struct Remove_Context));
+    rcc->gns = gns;
+    rcc->path = strdup (path);
+    GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, NULL, 
&check_name_validity_and_remove_proc, rcc);
+  }
+  g_free (name);
+}
+
+
+/**
+ * The user has selected a new record type.  Update the
+ * model, possibly invalidating (marking 'red') the existing
+ * value.
+ *
+ * @param renderer updated renderer
+ * @param path the path identifying the edited cell
+ * @param new_iter selected cell in the combo's model (with the record type)
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_type_cellrenderercombo_changed_cb (GtkCellRendererCombo *combo,
+                                                 gchar *path,
+                                                 GtkTreeIter *new_iter,
+                                                 gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  GtkTreeIter it;
+  GtkTreeIter child;
+  guint type;
+  int record_row;
+  char *type_str;
+  char *value_str;
+  char *name_str;
+  void *data;
+  size_t data_size;
+
+  gtk_tree_model_get(GTK_TREE_MODEL(gns->ls), new_iter, 0, &type, -1);
+  gtk_tree_model_get(GTK_TREE_MODEL(gns->ls), new_iter, 
GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPENAME, &type_str, -1);
+
+
+  /* check if this is a new record */
+  gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
+  gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_IS_RECORD_ROW, 
&record_row, -1);
+  gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NAME, &name_str, -1);
+
+  if (GNUNET_YES == record_row)
+  {
+    /* Updating an existing record */
+    gtk_tree_store_set(gns->ts, &it,
+                       GNS_TREESTORE_COL_RECORD_TYPE, type,
+                       GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str,
+                       -1);
+  }
+  else if ((NULL != name_str) && (0 != strcmp (NEW_NAME_STR, name_str)))
+  {
+    /* Adding a new record */
+
+    gtk_tree_store_insert_with_values(gns->ts, &child , &it, 0,
+        GNS_TREESTORE_COL_NAME, name_str,
+        GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE,
+        GNS_TREESTORE_COL_RECORD_TYPE, type,
+        GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str,
+        GNS_TREESTORE_COL_EXP_TIME_AS_STR, EXPIRE_NEVER_STRING,
+       GNS_TREESTORE_COL_EXP_TIME, GNUNET_TIME_UNIT_FOREVER_ABS,
+        GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE,
+        GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_YES,
+        GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES,
+        -1);
+    gtk_tree_view_expand_row (gns->tv, gtk_tree_model_get_path(gns->tm, &it), 
0);
+
+  }
+  GNUNET_free (type_str);
+
+  /* check if value is still valid */
+  gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_VAL_AS_STR, &value_str, 
-1);
+  if (NULL != value_str)
+  {
+    if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value (type,
+                                      value_str,
+                                      &data,
+                                      &data_size))
+      gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", 
-1);
+    else
+      gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, NULL, -1);
+    GNUNET_free (value_str);
+  }
+  else if (NULL == value_str)
+  {
+    /* Empty value field */
+    if (GNUNET_YES == record_row)
+      gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", 
-1);
+    else
+      gtk_tree_store_set (gns->ts, &child, GNS_TREESTORE_COL_VAL_COLOR, "red", 
-1);
+  }
+
+  check_name_validity_and_commit (gns, path, NULL);
+  GNUNET_free_non_null (name_str);
+}
+
+
+/**
+ * The user has toggled the 'public' checkmark of a cell.  Update the
+ * model.
+ *
+ * @param renderer updated renderer
+ * @param path the path identifying the edited cell
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_ispublic_cellrenderertoggle_toggled_cb (GtkCellRendererToggle 
*cell_renderer,
+                                                      gchar *path,
+                                                      gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  GtkTreeIter it;
+  gboolean value;
+
+  gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
+  gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_IS_PUBLIC, &value, -1);
+  gtk_tree_store_set(gns->ts, &it, GNS_TREESTORE_COL_IS_PUBLIC, !value, -1);
+
+  check_name_validity_and_commit (gns, path, NULL);
+}
+
+
+static char * 
+convert_time_to_string (struct GNUNET_TIME_Absolute t)
+{
+  time_t tt;
+  struct tm *time;
+  char *ret;
+
+  if (t.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
+      return GNUNET_strdup (_(EXPIRE_NEVER_STRING));
+  if (t.abs_value == GNUNET_TIME_UNIT_ZERO_ABS.abs_value)
+      return GNUNET_strdup (_(EXPIRE_INVALID_STRING));
+
+  tt = t.abs_value / 1000;
+  time = localtime (&tt);
+
+  GNUNET_asprintf(&ret, "%02u/%02u/%04u %02u:%02u",time->tm_mon, 
time->tm_mday, 1900 + time->tm_year, time->tm_hour, time->tm_min);
+  return ret;
+}
+
+
+static int 
+check_time (const char * text)
+{
+  unsigned int t_mon;
+  unsigned int t_day;
+  unsigned int t_year;
+  unsigned int t_hrs;
+  unsigned int t_min;
+
+  int count = SSCANF (text, "%02u/%02u/%04u %02u:%02u", &t_mon, &t_day, 
&t_year, &t_hrs, &t_min);
+  if ((EOF == count) || (5 != count))
+    return GNUNET_SYSERR;
+
+  if (t_mon > 12)
+    return GNUNET_SYSERR;
+  if (t_day > 31)
+    return GNUNET_SYSERR;
+  if (t_hrs > 24)
+    return GNUNET_SYSERR;
+  if (t_min > 59)
+      return GNUNET_SYSERR;
+
+  return GNUNET_OK;
+}
+
+
+static const struct GNUNET_TIME_Absolute
+convert_string_to_abs_time (const char * text)
+{
+  static struct GNUNET_TIME_Absolute abs_t;
+  struct tm time;
+  time_t t;
+
+  int t_mon;
+  int t_day;
+  int t_year;
+  int t_hrs;
+  int t_min;
+
+  GNUNET_assert (NULL != text);
+
+  if (0 == strcmp(text, EXPIRE_NEVER_STRING))
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
+
+  memset (&time, '\0', sizeof (struct tm));
+
+  if (GNUNET_SYSERR == check_time(text))
+  {
+    GNUNET_break (0);
+    return GNUNET_TIME_UNIT_ZERO_ABS;
+  }
+
+  int count = SSCANF (text, "%02d/%02d/%04d %02d:%02d", &t_mon, &t_day, 
&t_year, &t_hrs, &t_min);
+  if ((EOF == count) || (5 != count))
+    return GNUNET_TIME_UNIT_ZERO_ABS;
+
+  time.tm_mon = (t_mon - 1);
+  time.tm_mday = t_day;
+  time.tm_year = t_year - 1900;
+  time.tm_hour = (t_hrs);
+  time.tm_min = t_min;
+
+  t = mktime (&time);
+  if (-1 == t)
+    return GNUNET_TIME_UNIT_ZERO_ABS;
+
+  abs_t.abs_value = t * 1000;
+
+  return abs_t;
+}
+
+
+/**
+ * The user has edited a 'expiration' cell.  Update the model.
+ *
+ * @param renderer updated renderer
+ * @param path the path identifying the edited cell
+ * @param new_text the new expiration time
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_expiration_cellrenderertext_edited_cb (GtkCellRendererText 
*renderer,
+                                                     gchar *path,
+                                                     gchar *new_text,
+                                                     gpointer user_data)
+{
+  struct GNUNET_GNS_Context * gns = user_data;
+  GtkTreeIter it;
+  struct GNUNET_TIME_Absolute abstime;
+  gboolean is_rel;
+  char *old_text;
+
+  if ((NULL != new_text))
+  {
+    gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
+    gtk_tree_model_get(gns->tm, &it,
+                       GNS_TREESTORE_COL_EXP_TIME_AS_STR, &old_text,
+                       GNS_TREESTORE_COL_EXP_TIME_IS_REL, &is_rel,
+                       -1);
+    if (0 == strcmp(new_text, old_text))
+      return;
+
+    if ((0 == strcmp(new_text,"")) || (0 == 
strcmp(new_text,EXPIRE_NEVER_STRING)))
+    {
+      new_text = EXPIRE_NEVER_STRING;
+      abstime = GNUNET_TIME_UNIT_FOREVER_ABS;
+    }
+    else
+    {
+      if (GNUNET_SYSERR == check_time(new_text))
+      {
+        gtk_tree_store_set (gns->ts, &it,
+                            GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
+                            GNS_TREESTORE_COL_EXP_TIME_COLOR, "red",
+                            GNS_TREESTORE_COL_EXP_TIME, 0,
+                            -1);
+        abstime = GNUNET_TIME_UNIT_ZERO_ABS;
+        return;
+      }
+      /* TODO: fix this when we have relative time */
+      if (TRUE == is_rel)
+      {
+        abstime = convert_string_to_abs_time(new_text);
+      }
+      else
+      {
+        abstime = convert_string_to_abs_time(new_text);
+      }
+    }
+    gtk_tree_store_set (gns->ts, &it,
+                        GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
+                        GNS_TREESTORE_COL_EXP_TIME, abstime.abs_value,
+                        GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL,
+                        -1);
+    check_name_validity_and_commit (gns, path, NULL);
+  }
+}
+
+
+/**
+ * The user has edited a 'value' cell.  Update the model,
+ * including the status on the consistency of the value with
+ * the type.
+ *
+ * @param renderer updated renderer
+ * @param path the path identifying the edited cell
+ * @param new_text the new value
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_value_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
+                                                gchar *path,
+                                                gchar *new_text,
+                                                gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  GtkTreeModel *tm = GTK_TREE_MODEL(gns->ts);
+  GtkTreeIter it;
+  size_t data_size;
+  void * data;
+  int type;
+  gchar * old_value;
+
+  if (0 != strcmp(new_text,""))
+  {
+    gtk_tree_model_get_iter_from_string(tm, &it, path);
+    gtk_tree_model_get(tm, &it,
+        GNS_TREESTORE_COL_RECORD_TYPE, &type,
+        GNS_TREESTORE_COL_VAL_AS_STR, &old_value,
+        -1);
+
+    if (old_value != NULL)
+    {
+       if (0 == strcmp(new_text, old_value))
+       {
+         GNUNET_free (old_value);
+         return;
+       }
+       GNUNET_free (old_value);
+    }
+
+    if (GNUNET_OK == GNUNET_NAMESTORE_string_to_value (type,
+                                      new_text,
+                                      &data,
+                                      &data_size))
+    {
+      gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, NULL, -1);
+      gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_AS_STR, 
new_text, -1);
+      check_name_validity_and_commit (gns, path, NULL);
+    }
+    else
+    {
+      gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", 
-1);
+      gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_AS_STR, 
new_text, -1);
+    }
+  }
+}
+
+
+/**
+ * The user has edited a 'name' cell.  Update the model (and if needed
+ * create another fresh line for additional records).
+ *
+ * @param renderer updated renderer
+ * @param path the path identifying the edited cell
+ * @param new_text the new name
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
+                                               gchar *path,
+                                               gchar *new_text,
+                                               gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  GtkTreeIter it;
+  GtkTreeIter child;
+  GtkTreeModel *tm = GTK_TREE_MODEL(gns->ts);
+  int not_dummy;
+  char *name;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", path, 
new_text);
+  if ((0 == strcmp (new_text, NEW_NAME_STR)) || (0 == strcmp (new_text, "")))
+    return;
+
+  gtk_tree_model_get_iter_from_string(tm, &it, path);
+  gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, -1);
+  gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NAME, &name, -1);
+
+  if (not_dummy == GNUNET_NO)
+  {
+    /* update name */
+    gtk_tree_store_set (gns->ts, &it,
+                        GNS_TREESTORE_COL_NAME, new_text,
+                        GNS_TREESTORE_COL_RECORD_TYPE, 0,
+                        GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, 
_(NEW_RECORD_STR),
+                        GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES,
+                        -1);
+    check_name_validity_and_commit (gns, 
gtk_tree_model_get_string_from_iter(gns->tm, &it), name);
+
+    /* add a new dummy line */
+    gtk_tree_store_insert_with_values (gns->ts, &it,NULL, 0,
+        GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR),
+        GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
+        GNS_TREESTORE_COL_RECORD_TYPE, 1,
+        GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_NO,
+        GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO,
+        -1);
+  }
+  else
+  {
+    /* update name */
+    gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_NAME, new_text, -1);
+
+    if (TRUE == gtk_tree_model_iter_children (gns->tm, &child, &it))
+    {
+      do
+      {
+        gtk_tree_store_set (gns->ts, &child,
+                           GNS_TREESTORE_COL_NAME, &new_text,
+                           -1);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", 
path, new_text);
+      }
+      while (TRUE == gtk_tree_model_iter_next (gns->tm, &child));
+    }
+
+    check_name_validity_and_commit (gns, 
gtk_tree_model_get_string_from_iter(gns->tm, &it), name);
+  }
+
+  if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (new_text))
+  {
+    gtk_tree_store_set (gns->ts, &it,
+                        GNS_TREESTORE_COL_NAME_COLOR, "red",
+                        -1);
+  }
+  else
+  {
+    gtk_tree_store_set (gns->ts, &it,
+                        GNS_TREESTORE_COL_NAME_COLOR, NULL,
+                        -1);
+  }
+}
+
+
+/**
+ * The zone treeview pop up menu is supposed to be created.
+ * (Note: this is not the only method that might need to be
+ * written to handle events to create pop up menus; right-clicks
+ * might need to be managed separately).
+ *
+ * @param widget the widget
+ * @param user_data unused
+ * @return TRUE if a menu was activated
+ */
+gboolean
+GNUNET_GNS_GTK_main_treeview_popup_menu_cb (GtkWidget *widget,
+                                           gpointer user_data)
+{  
+  struct GNUNET_GNS_Context *gns = user_data;
+  GtkTreeModel *tm;
+  GtkTreeIter it;
+  GtkMenu *popup;
+  GtkTreeSelection * ts;
+  int not_dummy;
+
+  ts = gtk_tree_view_get_selection(gns->tv);
+  if (! gtk_tree_selection_get_selected (ts, &tm, &it))
+    return TRUE;
+  gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, 
&not_dummy, -1);
+  if (GNUNET_NO == not_dummy)
+    return TRUE;
+
+  popup  = GTK_MENU(gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_delete_popup_menu"));
+  gtk_widget_show_all (GTK_WIDGET(popup));
+  gtk_menu_popup(popup, NULL, NULL, NULL, NULL, 0, 0);
+  return TRUE;
+}
+
+
+static void
+set_relative_expiration_time (struct GNUNET_GNS_Context *gns, struct 
GNUNET_TIME_Relative reltime)
+{
+  GtkTreeIter it;
+  GtkTreeIter parent;
+  GtkCellRendererText *renderer;
+  GtkTreeModel *tm;
+  GtkTreeSelection * ts = gtk_tree_view_get_selection(gns->tv);
+  gboolean has_parent;
+  struct GNUNET_TIME_Absolute abstime;
+  char *path;
+  int not_dummy;
+
+  if (! gtk_tree_selection_get_selected (ts, &tm, &it))
+    return;
+
+  gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, -1);
+  if (GNUNET_NO == not_dummy)
+    return;
+
+  /* Has parent? */
+  has_parent = gtk_tree_model_iter_parent (tm, &parent, &it);
+
+  if (FALSE == has_parent)
+    return;
+
+  abstime = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), reltime);
+
+  /* this is a single record */
+  renderer = GTK_CELL_RENDERER_TEXT((gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_name_cellrenderertext")));
+  path = gtk_tree_model_get_string_from_iter (tm, &it);
+  GNUNET_GNS_GTK_expiration_cellrenderertext_edited_cb (renderer,
+                                                        path,
+                                                        convert_time_to_string 
(abstime),
+                                                        gns);
+}
+
+
+gboolean
+GNUNET_GNS_GTK_main_treeview_popup_menu_exp1d_cb (GtkWidget *widget,
+                                            gpointer user_data)
+{
+  set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_DAYS);
+  return TRUE;
+}
+
+
+gboolean
+GNUNET_GNS_GTK_main_treeview_popup_menu_exp1w_cb (GtkWidget *widget,
+                                            gpointer user_data)
+{
+  set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_WEEKS);
+  return TRUE;
+}
+
+
+gboolean
+GNUNET_GNS_GTK_main_treeview_popup_menu_exp1y_cb (GtkWidget *widget,
+                                            gpointer user_data)
+{
+  set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_YEARS);
+  return TRUE;
+}
+
+
+gboolean
+GNUNET_GNS_GTK_main_treeview_popup_menu_expinf_cb (GtkWidget *widget,
+                                            gpointer user_data)
+{
+  set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_FOREVER_REL);
+  return TRUE;
+}
+
+
+gboolean
+GNUNET_GNS_GTK_main_treeview_button_press_popup_menu_cb (GtkWidget *widget, 
GdkEventButton *event, gpointer user_data)
+{
+  /* Check for right click*/
+  if (NULL == widget)
+    return FALSE;
+  if (event->type == GDK_BUTTON_PRESS  &&  event->button == 3)
+    GNUNET_GNS_GTK_main_treeview_popup_menu_cb (widget, user_data);
+  return FALSE;
+}
+
+
+gboolean
+GNUNET_GNS_GTK_main_treeview_key_press_popup_menu_cb (GtkWidget *widget, 
GdkEventKey  *event, gpointer user_data)
+{
+  /* Check for delete key */
+  if ((event->type == GDK_KEY_PRESS) && (GDK_KEY_Delete == event->keyval))
+    GNUNET_GNS_GTK_main_treeview_popup_menu_cb (widget, user_data);
+  return FALSE;
+}
+
+
+struct ZoneIteration_Context
+{
+  struct GNUNET_GNS_Context *gns;
+  struct GNUNET_CRYPTO_ShortHashCode zone;
+  struct GNUNET_NAMESTORE_ZoneIterator * it;
+  char *label;
+};
+
+
+void
+GNUNET_GNS_GTK_delete_popup_menu_delete_cb (GtkMenuItem *menuitem,
+                                                 gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  GtkTreeIter it;
+  GtkTreeModel *tm;
+  GtkTreeSelection * ts;
+  int not_dummy;
+  char *path;
+
+  ts = gtk_tree_view_get_selection(gns->tv);
+  if (gtk_tree_selection_get_selected (ts, &tm, &it))
+  {
+    gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, 
-1);
+    if (GNUNET_NO == not_dummy)
+      return; /* do not delete the dummy line */
+
+    path = gtk_tree_model_get_string_from_iter (gns->tm, &it);
+    check_name_validity_and_remove(gns, path);
+    g_free (path);
+  }
+}
+
+
+static void
+zone_iteration_proc (void *cls,
+                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded 
*zone_key,
+                          struct GNUNET_TIME_Absolute expire,
+                          const char *name,
+                          unsigned int rd_count,
+                          const struct GNUNET_NAMESTORE_RecordData *rd,
+                          const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+  struct ZoneIteration_Context * zc_ctx = cls;
+  GtkTreeIter iter_name;
+  GtkTreeIter iter_record;
+  GtkEntry *pseu_entry;
+  int c;
+  int time_is_relative;
+
+  char *exp;
+  char *val;
+  char * type_str;
+  int public;
+  guint64 exp_t;
+
+  GNUNET_assert (zc_ctx != NULL);
+  if ((NULL == zone_key) && (NULL == name))
+  {
+    struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
+    GNUNET_CRYPTO_short_hash_to_enc(&zc_ctx->zone, &shenc);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone `%s 'iteration done\n", &shenc);
+    pseu_entry = GTK_ENTRY((gtk_builder_get_object (zc_ctx->gns->builder, 
"GNUNET_GNS_GTK_pseu_entry")));
+    if (zc_ctx->label == NULL)
+      GNUNET_asprintf(&zc_ctx->label, "%s", PSEU_EMPTY_STR);
+    gtk_entry_set_text (pseu_entry, zc_ctx->label);
+    zc_ctx->gns->iteration = GNUNET_NO;
+    GNUNET_free (zc_ctx->label);
+    GNUNET_free (zc_ctx);
+    return;
+  }
+
+
+  struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
+  GNUNET_CRYPTO_short_hash_to_enc(&zc_ctx->zone, &shenc);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone `%s' iteration result `%s', %u 
records\n",
+      &shenc, name, rd_count);
+
+  GNUNET_assert(GTK_IS_TREE_STORE(zc_ctx->gns->ts));
+  gtk_tree_store_append(zc_ctx->gns->ts, &iter_name, NULL);
+  gtk_tree_store_set(zc_ctx->gns->ts, &iter_name,
+                     GNS_TREESTORE_COL_NAME, name,
+                     GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
+                     GNS_TREESTORE_COL_RECORD_TYPE, 0,
+                     GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
+                     GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO,
+                     GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES,
+                     -1);
+
+  if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (name))
+  {
+    gtk_tree_store_set (zc_ctx->gns->ts, &iter_name,
+                        GNS_TREESTORE_COL_NAME_COLOR, "red",
+                        -1);
+  }
+  /* Append elements for records */
+  for (c = 0; c < rd_count; c ++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %u: type %u flags %u 
expiration %llu data_size %u\n",
+        c, rd[c].record_type, rd[c].flags, rd[c].expiration_time, 
rd[c].data_size);
+
+    /* Set public toggle */
+    if ((rd[c].flags & GNUNET_NAMESTORE_RF_PRIVATE) == 
GNUNET_NAMESTORE_RF_PRIVATE)
+    {
+      public = GNUNET_NO;
+    }
+    else
+    {
+      public = GNUNET_YES;
+    }
+
+    /* Expiration time */
+    time_is_relative = GNUNET_NO;
+
+    if (GNUNET_YES == time_is_relative)
+    {
+      /* TODO: FIX THIS WHEN WE HAVE RELATIVE TIME */
+      struct GNUNET_TIME_Relative rel_time = GNUNET_TIME_UNIT_ZERO;
+      struct GNUNET_TIME_Absolute exp_abs;
+      exp_abs = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), rel_time);
+      exp_t = exp_abs.abs_value;
+      exp = convert_time_to_string (exp_abs);
+    }
+    else
+    {
+      struct GNUNET_TIME_Absolute exp_abs;
+
+      exp_abs.abs_value = rd[c].expiration_time;
+      exp_t = exp_abs.abs_value;
+      exp = convert_time_to_string (exp_abs);
+    }
+    /* value */
+    val = GNUNET_NAMESTORE_value_to_string (rd[c].record_type,
+                                            rd[c].data,
+                                            rd[c].data_size);
+    if (NULL == val)
+      GNUNET_asprintf(&val, "%s", EXPIRE_INVALID_STRING);
+
+    if (NULL != GNUNET_NAMESTORE_number_to_typename(rd[c].record_type))
+      type_str = strdup 
(GNUNET_NAMESTORE_number_to_typename(rd[c].record_type));
+    else
+      GNUNET_asprintf(&type_str, "%s", EXPIRE_INVALID_STRING);
+
+    if ((0 ==strcmp (name, ROOT_STR)) && (GNUNET_NAMESTORE_TYPE_PSEU == 
rd[c].record_type))
+    {
+        zc_ctx->label = strdup(val);
+        zc_ctx->gns->iteration = GNUNET_YES;
+    }
+    else
+    {
+      gtk_tree_store_insert_with_values(zc_ctx->gns->ts, &iter_record , 
&iter_name, 0,
+                                         GNS_TREESTORE_COL_NAME, name,
+                                         GNS_TREESTORE_COL_NAME_IS_VISIBLE, 
FALSE,
+                                         GNS_TREESTORE_COL_RECORD_TYPE, 
rd[c].record_type,
+                                         GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, 
type_str,
+                                         GNS_TREESTORE_COL_IS_PUBLIC, public,
+                                         GNS_TREESTORE_COL_EXP_TIME, exp_t,
+                                         GNS_TREESTORE_COL_EXP_TIME_AS_STR, 
exp,
+                                         GNS_TREESTORE_COL_EXP_TIME_IS_REL, 
time_is_relative,
+                                         GNS_TREESTORE_COL_VAL_AS_STR, val,
+                                         GNS_TREESTORE_COL_IS_RECORD_ROW, 
GNUNET_YES,
+                                         GNS_TREESTORE_COL_NOT_DUMMY_ROW, 
GNUNET_YES,
+                                         -1);
+    }
+    GNUNET_free (type_str);
+    GNUNET_free (exp);
+    GNUNET_free (val);
+  }
+
+  GNUNET_NAMESTORE_zone_iterator_next(zc_ctx->it);
+}
+
+
+/**
+ * The zone treeview was realized.   Setup the model.
+ *
+ * @param widget the widget
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_main_treeview_realize_cb (GtkWidget *widget,
+                                        gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  struct ZoneIteration_Context *zc_ctx;
+  GtkTreeIter toplevel;
+
+  /* Append a top level row and leave it empty */
+  gtk_tree_store_insert_with_values(gns->ts, &toplevel, NULL, 0,
+                                     GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR),
+                                     GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
+                                     GNS_TREESTORE_COL_RECORD_TYPE, 1,
+                                     GNS_TREESTORE_COL_IS_RECORD_ROW, 
GNUNET_NO,
+                                     GNS_TREESTORE_COL_NOT_DUMMY_ROW, 
GNUNET_NO,
+                                     -1);
+
+  zc_ctx = GNUNET_malloc (sizeof (struct ZoneIteration_Context));
+  zc_ctx->gns = user_data;
+  zc_ctx->zone = gns->zone;
+  zc_ctx->it = GNUNET_NAMESTORE_zone_iteration_start(gns->ns, &gns->zone,
+      GNUNET_NAMESTORE_RF_NONE,
+      GNUNET_NAMESTORE_RF_NONE,
+      &zone_iteration_proc,
+      zc_ctx);
+}
+
+
+
+static void 
+pseu_change_cont (void *cls,
+                 int32_t success,
+                 const char *emsg)
+{
+  struct GNUNET_GNS_Context *gns = cls;
+  GtkWidget *dialog;
+  if (GNUNET_SYSERR == success)
+  {
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("New Pseudonym could not be set: 
`%s'\n"), emsg);
+  dialog = gtk_message_dialog_new (GTK_WINDOW (gns->main_window),
+                                   GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_ERROR,
+                                   GTK_BUTTONS_CLOSE,
+                                   _("New Pseudonym could not be set: `%s'\n"),
+                                   emsg);
+    g_signal_connect_swapped (dialog, "response",
+                              G_CALLBACK (gtk_widget_destroy),
+                              dialog);
+    gtk_widget_show_all (dialog);
+  }
+}
+
+
+/**
+ * Task run on shutdown.
+ *
+ * @param cls unused
+ * @param tc scheduler context, unused
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+  struct GNUNET_GNS_Context *gns = cls;
+  if (NULL == gns)
+    return;
+  if (NULL != gns->ns)
+  {
+    GNUNET_NAMESTORE_disconnect (gns->ns, GNUNET_NO);
+    gns->ns = NULL;
+  }
+  if (NULL != gns->pkey)
+  {
+    GNUNET_CRYPTO_rsa_key_free (gns->pkey);
+    gns->pkey = NULL;
+  }
+  if (NULL != zonekey_directory)
+  {
+    GNUNET_free (zonekey_directory);
+    zonekey_directory = NULL;
+  }
+  GNUNET_free (gns);
+}
+
+
+
+gboolean
+GNUNET_GNS_GTK_pseu_entry_enter_cb (GtkWidget *widget,
+                                    GdkEvent  *event,
+                                    gpointer   user_data)
+{
+  const gchar * pseu;
+
+  pseu = gtk_entry_get_text (GTK_ENTRY(widget));
+
+  if ((pseu == NULL) || (0 == strcmp (pseu, "")))
+  {
+    //gtk_entry_set_text (GTK_ENTRY(widget), PSEU_EMPTY_STR);
+  }
+  return FALSE;
+}
+
+
+
+
+/**
+ * The user edited the preferred name (PSEU) of this namespace.
+ * Push the update to the namestore.
+ *
+ * @param editable the edited widget
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_pseu_entry_changed_cb (GtkEditable *editable,
+                                     gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  struct GNUNET_NAMESTORE_RecordData rd;
+  const gchar * pseu;
+
+  pseu = gtk_entry_get_text (GTK_ENTRY(editable));
+  if ((pseu != NULL) && (0 != strcmp (pseu, PSEU_EMPTY_STR)) && (0 != strcmp 
("", pseu)) && (GNUNET_NO == gns->iteration))
+  {
+
+    rd.record_type = GNUNET_NAMESTORE_TYPE_PSEU;
+    rd.expiration_time = UINT64_MAX;
+    rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
+    rd.data_size = strlen (pseu) + 1;
+    rd.data = strdup (pseu);
+    GNUNET_NAMESTORE_record_create(gns->ns, gns->pkey, "+", &rd, 
pseu_change_cont, gns);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New Pseudonym is `%s' %u\n", (char 
*) rd.data, rd.data_size);
+  }
+  else if ((0 != strcmp (pseu, PSEU_EMPTY_STR)) && ((pseu == NULL) || (0 == 
strcmp ("", pseu))))
+  {
+    gtk_entry_set_text (GTK_ENTRY(editable), PSEU_EMPTY_STR);
+  }
+
+}
+
+/**
+ * The user toggled the 'autoshort' option.  Update the configuration.
+ *
+ * @param checkmenuitem the menu item
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_autoshort_imagemenuitem_toggled_cb (GtkCheckMenuItem 
*checkmenuitem,
+                                                  gpointer user_data)
+{
+  struct GNUNET_GNS_Context *gns = user_data;
+  GtkWidget *dialog;
+  struct GNUNET_CONFIGURATION_Handle *cfg = (struct 
GNUNET_CONFIGURATION_Handle *) get_configuration();
+
+  gboolean state = gtk_check_menu_item_get_active (gns->shorten_menu);
+  if (TRUE == state)
+    GNUNET_CONFIGURATION_set_value_string(cfg,"gns", "AUTO_IMPORT_PKEY","YES");
+  else
+    GNUNET_CONFIGURATION_set_value_string(cfg,"gns", "AUTO_IMPORT_PKEY","NO");
+
+  char * cfgfile = strdup (GNUNET_GTK_main_loop_get_configuration_file(ml));
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write(cfg, cfgfile))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Changes to autoshorten could not 
be written to configuration file: `%s'\n"), cfgfile);
+    dialog = gtk_message_dialog_new (GTK_WINDOW (gns->main_window),
+                                     GTK_DIALOG_DESTROY_WITH_PARENT,
+                                     GTK_MESSAGE_ERROR,
+                                     GTK_BUTTONS_CLOSE,
+                                     _("Changes to autoshorten option could 
not be written to configuration file: `%s'\n"),
+                                     cfgfile);
+    g_signal_connect_swapped (dialog, "response",
+                              G_CALLBACK (gtk_widget_destroy),
+                              dialog);
+    gtk_widget_show_all (dialog);
+  }
+  GNUNET_free (cfgfile);
+}
+
+
+/**
+ * The user selected 'NEW' in the menu.  Open a dialog to enter a filename
+ * to create a new zone (for editing).
+ *
+ * @param checkmenuitem the menu item
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_new_imagemenuitem_activate_cb (GtkMenuItem *menuitem,
+                                             gpointer user_data)
+{
+  GNUNET_break (0); // FIXME, not implemented
+}
+
+
+/**
+ * Function called from the open-directory dialog upon completion.
+ *
+ * @param dialog the pseudonym selection dialog
+ * @param response_id response code from the dialog
+ * @param user_data the builder of the dialog
+ */
+void
+GNUNET_GNS_GTK_zone_open_dialog_response_cb (GtkDialog * dialog,
+                                            gint response_id,
+                                            gpointer user_data)
+{
+  char *filename;
+
+  if (GTK_RESPONSE_OK != response_id)
+  {
+    gtk_widget_destroy (GTK_WIDGET (dialog));
+    g_object_unref (G_OBJECT (dialog));
+    return;
+  }
+  filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER 
(dialog));
+  gtk_widget_destroy (GTK_WIDGET (dialog));
+  g_object_unref (G_OBJECT (dialog));
+
+  /* FIXME: move to new zone 'filename' */
+  fprintf (stderr, "Got zone `%s'\n", filename);
+  GNUNET_free (filename);  
+}
+
+
+/**
+ * The user selected 'OPEN' in the menu.  Open a dialog to select
+ * a different zonefile (for editing).
+ *
+ * @param checkmenuitem the menu item
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_open_imagemenuitem_activate_cb (GtkMenuItem *menuitem,
+                                              gpointer user_data)
+{
+  GtkWidget *ad;
+  GtkBuilder *builder;
+  GtkWidget *toplevel;
+  GtkFileFilter *ff;
+  GtkFileChooser *fc;
+
+  builder =
+    GNUNET_GTK_get_new_builder ("gnunet_gns_gtk_zone_open.glade", NULL);
+  if (NULL == builder)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  /* This file filter could be set with glade if we use gtk3
+   * With gtk2 we have to set it manually */
+  ff = GTK_FILE_FILTER (gtk_builder_get_object
+      (builder, "GNUNET_GNS_GTK_zone_open_filefilter"));
+  gtk_file_filter_add_pattern (ff, "*.zkey");
+
+  ad = GTK_WIDGET (gtk_builder_get_object
+                   (builder, "GNUNET_GNS_GTK_zone_open_filechooserdialog"));
+
+  if (GTK_IS_FILE_CHOOSER(ad))
+  {
+    fc = GTK_FILE_CHOOSER(ad);
+    if (NULL != fc)
+      gtk_file_chooser_set_current_folder(fc, zonekey_directory);
+  }
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menuitem));
+  if (GTK_IS_WINDOW (toplevel))
+    gtk_window_set_transient_for (GTK_WINDOW (ad), GTK_WINDOW (toplevel));
+  gtk_window_present (GTK_WINDOW (ad));
+}
+
+
+/**
+ * The user clicked on the 'copy' button.  Copy the full string
+ * with the hash of our public key to the clipboard.
+ *
+ * @param button the button that was clicked
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_public_key_copy_button_clicked_cb (GtkButton *button,
+                                                 gpointer user_data)
+{
+  GtkClipboard *cb;
+
+  cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+  gtk_clipboard_set_text (cb, zone_as_string, -1);
+}
+
+
+
+/**
+ * Callback invoked if the application is supposed to exit (via menu).
+ *
+ * @param menuitem the quit menu
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_quit_imagemenuitem_activate_cb (GtkMenuItem *menuitem,
+                                              gpointer user_data)
+{
+  GNUNET_GTK_tray_icon_destroy ();
+  GNUNET_GTK_main_loop_quit (ml);
+  GNUNET_SCHEDULER_add_now (&shutdown_task, user_data);
+}
+
+
+/**
+ * Callback invoked if the application is supposed to exit (via window-close).
+ *
+ * @param widget the main window
+ * @param event deletion event
+ * @param user_data unused
+ */
+void
+GNUNET_GNS_GTK_main_window_delete_event_cb (GtkWidget *widget,
+                                           GdkEvent *event,
+                                           gpointer user_data)
+{
+  GNUNET_GTK_tray_icon_destroy ();
+  GNUNET_GTK_main_loop_quit (ml);
+  GNUNET_SCHEDULER_add_now (&shutdown_task, user_data);
+}
+
+
+static void
+close_error_box (GtkDialog *dialog,
+                gint       response_id,
+                gpointer   user_data)
+{
+  gtk_widget_destroy (GTK_WIDGET(dialog));
+  GNUNET_GNS_GTK_shutdown (user_data);
+}
+
+
+static void
+namestore_service_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
+{
+  struct GNUNET_GNS_Context *gns = NULL;
+  struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
+  GtkWidget *dialog;
+  char *label;
+  char *keyfile;
+  char *servicehome;
+
+  gns = GNUNET_malloc (sizeof (struct GNUNET_GNS_Context));
+
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT) != 0)
+  {
+   char * message = _("Namestore service is not running!\n");
+   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, message);
+   dialog = gtk_message_dialog_new (GTK_WINDOW (gns->main_window),
+                                    GTK_DIALOG_DESTROY_WITH_PARENT,
+                                    GTK_MESSAGE_ERROR,
+                                    GTK_BUTTONS_CLOSE,
+                                    "%s",
+                                    message);
+
+   g_signal_connect (dialog, "response", G_CALLBACK(close_error_box), gns);
+   gtk_widget_show_all (dialog);
+   return;
+  }
+
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (get_configuration 
(),
+                                                            "PATHS",
+                                                            "SERVICEHOME",
+                                                            &servicehome))
+  {
+    GNUNET_asprintf(&zonekey_directory, "");
+  }
+  else
+  {
+    GNUNET_asprintf(&zonekey_directory, "%s%s%s",servicehome, 
DIR_SEPARATOR_STR, "gns");
+    GNUNET_free (servicehome);
+  }
+
+  /* setup crypto keys */
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (get_configuration 
(),
+                                                            "gns",
+                                                            "ZONEKEY",
+                                                            &keyfile))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Option `%s' missing in section `%s'\n"), "ZONEKEY", "gns");
+    return;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using `%s'\n", keyfile);
+  gns->pkey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+  GNUNET_free (keyfile);
+  keyfile = NULL;
+  if (NULL == gns->pkey)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to read or create private zone key\n"));
+    return;
+  }
+  GNUNET_CRYPTO_rsa_key_get_public (gns->pkey, &gns->pubkey);
+  GNUNET_CRYPTO_short_hash (&gns->pubkey,
+                            sizeof (struct 
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                            &gns->zone);
+  GNUNET_CRYPTO_short_hash_to_enc(&gns->zone, &shenc);
+
+  /* connect to namestore */
+  gns->ns = GNUNET_NAMESTORE_connect (get_configuration ());
+  if (NULL == gns->ns)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to connect to namestore\n"));
+    return;
+  }
+
+  /* setup gui */
+  if (GNUNET_OK != GNUNET_GTK_main_loop_build_window (ml, gns))
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_add_now (&shutdown_task, gns);
+    return;
+  }
+  gns->builder = GNUNET_GTK_main_loop_get_builder(ml);
+  gns->main_window = GTK_WIDGET (get_object ("GNUNET_GNS_GTK_main_window"));
+  gns->ts  = GTK_TREE_STORE (gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_treestore"));
+  gns->ls =  GTK_LIST_STORE (gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_type_liststore"));
+  gns->tv =  GTK_TREE_VIEW (gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_main_treeview"));
+  gns->tm = GTK_TREE_MODEL(gns->ts);
+  gns->shorten_menu =  GTK_CHECK_MENU_ITEM(gtk_builder_get_object 
(gns->builder, "GNUNET_GNS_GTK_autoshort_imagemenuitem"));
+  if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (get_configuration (),
+                                                            "gns",
+                                                            
"AUTO_IMPORT_PKEY"))
+    gtk_check_menu_item_set_active (gns->shorten_menu, TRUE);
+  else
+    gtk_check_menu_item_set_active (gns->shorten_menu, FALSE);
+
+  /* TODO: implements menus */
+  gtk_widget_set_visible (GTK_WIDGET (gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_new_imagemenuitem")), FALSE);
+  gtk_widget_set_visible (GTK_WIDGET (gtk_builder_get_object (gns->builder, 
"GNUNET_GNS_GTK_open_imagemenuitem")), FALSE);
+
+  zone_as_string = GNUNET_strdup ((char *) &shenc);
+  label = g_markup_printf_escaped (_("<b>Editing zone %s</b>"),
+                                  zone_as_string);
+  gtk_label_set_markup (GTK_LABEL (get_object ("GNUNET_GNS_GTK_zone_label")),
+                       label);
+  g_free (label);
+
+}
+
+
+/* end of gnunet-setup-gns.c */

Added: gnunet-gtk/src/setup/gnunet-setup-namestore-config.c
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-namestore-config.c                        
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-namestore-config.c        2012-06-23 
18:57:21 UTC (rev 22229)
@@ -0,0 +1,112 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010, 2012 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-namestore-config.c
+ * @brief test datastore configuration
+ * @author Christian Grothoff
+ */
+#include "gnunet-setup.h"
+#include <gnunet/gnunet_namestore_plugin.h>
+
+
+/**
+ * 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)
+{
+  void *ret;
+
+  ret = GNUNET_PLUGIN_load (name, cfg);
+  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 (GNUNET_SETUP_get_object (name)));
+}
+
+
+static void
+hide (const char *name)
+{
+  gtk_widget_hide (GTK_WIDGET (GNUNET_SETUP_get_object (name)));
+}
+
+
+void
+GNUNET_setup_namestore_postgres_invalidate_cb ()
+{
+  hide ("GNUNET_setup_namestore_postgres_tab_ok_image");
+  hide ("GNUNET_setup_namestore_postgres_tab_error_image");
+}
+
+
+void
+GNUNET_setup_namestore_postgres_tab_test_button_clicked_cb (GtkWidget * widget,
+                                                            gpointer user_data)
+{
+  if (GNUNET_OK == test_config ("libgnunet_plugin_namestore_postgres"))
+  {
+    show ("GNUNET_setup_namestore_postgres_tab_ok_image");
+    hide ("GNUNET_setup_namestore_postgres_tab_error_image");
+  }
+  else
+  {
+    hide ("GNUNET_setup_namestore_postgres_tab_ok_image");
+    show ("GNUNET_setup_namestore_postgres_tab_error_image");
+  }
+}
+
+
+static void
+restart_namestore ()
+{
+  GNUNET_SCHEDULER_add_now (&GNUNET_SETUP_restart_namestore,
+                           NULL);
+}
+
+
+void
+GNUNET_setup_namestore_sqlite_radiobutton_toggled_cb (GtkToggleButton *tb,
+                                                     gpointer user_data)
+{
+  restart_namestore ();
+}
+
+
+void
+GNUNET_setup_namestore_postgres_radiobutton_toggled_cb (GtkToggleButton *tb,
+                                                       gpointer user_data)
+{
+  restart_namestore ();
+}
+
+
+/* end of gnunet-setup-namestore-config.c */

Added: gnunet-gtk/src/setup/gnunet-setup-namestore-plugins.c
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-namestore-plugins.c                       
        (rev 0)
+++ gnunet-gtk/src/setup/gnunet-setup-namestore-plugins.c       2012-06-23 
18:57:21 UTC (rev 22229)
@@ -0,0 +1,67 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 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-namestore-plugins.c
+ * @brief (de)sensitize namestore 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_namestore_sqlite_radiobutton_realize_cb (GtkWidget * widget,
+                                                     gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_namestore_sqlite");
+}
+
+
+void
+GNUNET_setup_namestore_postgres_radiobutton_realize_cb (GtkWidget * widget,
+                                                           gpointer user_data)
+{
+  test_plugin (widget, "libgnunet_plugin_namestore_postgres");
+}
+
+
+
+/* end of gnunet-setup-namestore-plugins.c */

Modified: gnunet-gtk/src/setup/gnunet-setup-options.c
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup-options.c 2012-06-23 18:50:13 UTC (rev 
22228)
+++ gnunet-gtk/src/setup/gnunet-setup-options.c 2012-06-23 18:57:21 UTC (rev 
22229)
@@ -717,659 +717,11 @@
 
 
 /**
- * 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,
-                                       GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, "",
-                                       GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT,
-                                       (guint) 80,
-                                       GNUNET_GTK_SETUP_GNS_MC_TARGETPORT,
-                                       (guint) 8080,
-                                       GNUNET_GTK_SETUP_GNS_MC_HOSTNAME,
-                                       "localhost4",
-                                       GNUNET_GTK_SETUP_GNS_MC_ISUDP, "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,
-                                           GNUNET_GTK_SETUP_GNS_MC_HOSTNAME,
-                                           sld,
-                                           GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT,
-                                           (guint) local_port,
-                                           GNUNET_GTK_SETUP_GNS_MC_TARGETPORT,
-                                           (guint) host_port,
-                                           
GNUNET_GTK_SETUP_GNS_MC_TARGETHOSTNAME,
-                                           hostname,
-                                           GNUNET_GTK_SETUP_GNS_MC_ISUDP,
-                                           (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,
-                          GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, &hostname,
-                          GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT, &srcport,
-                          GNUNET_GTK_SETUP_GNS_MC_TARGETPORT, &targetport,
-                          GNUNET_GTK_SETUP_GNS_MC_TARGETHOSTNAME, &targethost,
-                          GNUNET_GTK_SETUP_GNS_MC_ISUDP, &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);
-    if ((strlen (pos->udpred) > 0) || (strlen (pos->tcpred) > 0))
-      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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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, GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, &old, -1);
-  if ((0 != strlen (old)) && (0 == strlen (new_text)))
-  {
-    /* deletion */
-    gtk_list_store_remove (ls, &iter);
-    g_free (old);
-    /* update configuration */
-    update_vpn_dns_configuration (tm);
-    return;
-  }
-  /* update model */
-  gtk_list_store_set (ls, &iter,
-                      GNUNET_GTK_SETUP_GNS_MC_HOSTNAME, 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
-gns_name_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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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, GNUNET_GTK_SETUP_GNS_MC_ISUDP, 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
-gns_type_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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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,
-                      GNUNET_GTK_SETUP_GNS_MC_SOURCEPORT, (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
-gns_ttl_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 (GNUNET_SETUP_get_object ("GNUNET_setup_gns_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,
-                      GNUNET_GTK_SETUP_GNS_MC_TARGETHOSTNAME, 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
-gns_value_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;
-}
-
-
-
-/**
  * 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},
+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}
 };
 
@@ -1411,7 +763,7 @@
 
 
 /**
- * Hide "fs tab" if FS not active.
+ * Hide "fs" tab if FS not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_fs_tab[] = {
   {"GNUNET_setup_fs_main_vbox", "(^| )fs($| )", NULL},
@@ -1420,7 +772,7 @@
 
 
 /**
- * Hide "vpn tab" if VPN not active.
+ * Hide "vpn" tab if VPN not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_vpn_tab[] = {
   {"GNUNET_setup_vpn_vbox", "(^| )pt($| )", NULL},
@@ -1429,16 +781,17 @@
 
 
 /**
- * Hide "gns tab" if GNS not active.
+ * Hide "gns" and "namestore" tabs if GNS not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_gns_tab[] = {
   {"GNUNET_setup_gns_vbox", "(^| )gns($| )", NULL},
+  {"GNUNET_setup_namestore_vbox", "(^| )gns($| )", NULL},
   {NULL, NULL, NULL}
 };
 
 
 /**
- * Hide "tcp tab" if TCP not active.
+ * Hide "tcp" tab if TCP not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_tcp_tab[] = {
   {"GNUNET_setup_transport_tcp_vbox", "(^| )tcp($| )", NULL},
@@ -1447,7 +800,7 @@
 
 
 /**
- * Hide "udp tab" if UDP not active.
+ * Hide "udp" tab if UDP not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_udp_tab[] = {
   {"GNUNET_setup_transport_udp_vbox", "(^| )udp($| )", NULL},
@@ -1456,7 +809,7 @@
 
 
 /**
- * Hide "http tab" if HTTP not active.
+ * Hide "http" tab if HTTP not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_http_tab[] = {
   {"GNUNET_setup_transport_http_vbox", "(^| )http($| )", NULL},
@@ -1465,7 +818,7 @@
 
 
 /**
- * Hide "https tab" if HTTPS not active.
+ * Hide "https" tab if HTTPS not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_https_tab[] = {
   {"GNUNET_setup_transport_https_vbox", "(^| )https($| )", NULL},
@@ -1474,7 +827,7 @@
 
 
 /**
- * Hide "dv tab" if DV not active.
+ * Hide "dv" tab if DV not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_dv_tab[] = {
   {"GNUNET_setup_transport_dv_vbox", "(^| )dv($| )", NULL},
@@ -1483,7 +836,7 @@
 
 
 /**
- * Hide "wlan tab" if WLAN not active.
+ * Hide "wlan" tab if WLAN not active.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_wlan_tab[] = {
   {"GNUNET_setup_transport_wlan_vbox", "(^| )wlan($| )", NULL},
@@ -1548,6 +901,24 @@
 
 
 /**
+ * Hide "sqlite namestore" tab if sqlite not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification hide_sqlite_namestore_tab[] 
= {
+  {"GNUNET_setup_namestore_sqlite_label", "^sqlite$", NULL},
+  {NULL, NULL, NULL}
+};
+
+
+/**
+ * Hide "postgres datastore" tab if postgres not active.
+ */
+static struct GNUNET_SETUP_VisibilitySpecification 
hide_postgres_namestore_tab[] = {
+  {"GNUNET_setup_namestore_postgres_hbox", "^postgres$", NULL},
+  {NULL, NULL, NULL}
+};
+
+
+/**
  * Hide advertised TCP port if port is zero.
  */
 static struct GNUNET_SETUP_VisibilitySpecification hide_all_tcp_options[] = {
@@ -2541,6 +1912,45 @@
    NULL, NULL,
    NULL},
 
+
+  /* Namestore TAB */
+
+  {
+   "GNUNET_setup_namestore_sqlite_radiobutton",
+   "toggled",
+   "namestore",
+   "DATABASE",
+   gettext_noop ("Use sqLite to store names"),
+   "https://gnunet.org/configuration-namestore";,
+   &load_option_list /* abuse! */ ,
+   &save_option_list /* abuse! */ , "sqlite",
+   NULL, NULL,
+   hide_sqlite_namestore_tab},
+
+  {
+   "GNUNET_setup_namestore_postgres_radiobutton",
+   "toggled",
+   "namestore",
+   "DATABASE",
+   gettext_noop ("Use PostGres to store names"),
+   "https://gnunet.org/configuration-namestore";,
+   &load_option_list /* abuse! */ ,
+   &save_option_list /* abuse! */ , "postgres",
+   NULL, NULL,
+   hide_postgres_namestore_tab},
+
+  {
+   "GNUNET_setup_namestore_postgres_config_entry",
+   "changed",
+   "namestore-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, NULL,
+   NULL},
+
   /* GNS treeview */
 
   {
@@ -2555,75 +1965,6 @@
    NULL, NULL,
    hide_gns_tab},
 
-  {
-   "GNUNET_setup_gns_treeview",
-   NULL,
-   NULL,
-   NULL,
-   gettext_noop
-   ("Specification of .gnunet TLD"),
-   "https://gnunet.org/configuration-dns";,
-   &load_vpn_dns_configuration,
-   NULL, NULL,
-   NULL, NULL,
-   NULL},
-
-  {
-   "GNUNET_setup_gns_name_cellrenderertext",
-   "editing-started",
-   NULL,
-   NULL,
-   NULL,
-   "https://gnunet.org/configuration-dns";,
-   NULL,
-   &gns_name_install_edited_handler,
-   NULL,
-   NULL,
-   NULL,
-   NULL},
-
-  {
-   "GNUNET_setup_gns_type_cellrenderertext",
-   "editing-started",
-   NULL,
-   NULL,
-   NULL,
-   "https://gnunet.org/configuration-dns";,
-   NULL,
-   &gns_type_install_edited_handler,
-   NULL,
-   NULL,
-   NULL,
-   NULL},
-
-  {
-   "GNUNET_setup_gns_ttl_cellrenderertext",
-   "editing-started",
-   NULL,
-   NULL,
-   NULL,
-   "https://gnunet.org/configuration-dns";,
-   NULL,
-   &gns_ttl_install_edited_handler,
-   NULL,
-   NULL,
-   NULL,
-   NULL},
-
-  {
-   "GNUNET_setup_gns_value_cellrenderertext",
-   "editing-started",
-   NULL,
-   NULL,
-   NULL,
-   "https://gnunet.org/configuration-dns";,
-   NULL,
-   &gns_value_install_edited_handler,
-   NULL,
-   NULL,
-   NULL,
-   NULL},
-
   /* END of list */
 
   {NULL, NULL, NULL, NULL, NULL,
@@ -2631,4 +1972,5 @@
    NULL}
 };
 
+
 /* end of gnunet-setup-options.c */

Modified: gnunet-gtk/src/setup/gnunet-setup.c
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup.c 2012-06-23 18:50:13 UTC (rev 22228)
+++ gnunet-gtk/src/setup/gnunet-setup.c 2012-06-23 18:57:21 UTC (rev 22229)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2010 Christian Grothoff (and other contributing authors)
+     (C) 2010, 2011, 2012 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
@@ -53,9 +53,14 @@
 /**
  * Resolver process handle.
  */
-struct GNUNET_OS_Process *resolver;
+static struct GNUNET_OS_Process *resolver;
 
+/**
+ * Namestore process handle.
+ */
+static struct GNUNET_OS_Process *namestore;
 
+
 /**
  * Get an object from the main window.
  *
@@ -278,6 +283,25 @@
 
 
 /**
+ * Write final configuration to disk.
+ *
+ * @return GNUNET_OK on success
+ */
+static int 
+write_configuration ()
+{
+  struct GNUNET_CONFIGURATION_Handle *cfgDefault;
+  int ret;
+
+  cfgDefault = GNUNET_CONFIGURATION_create ();
+  (void) GNUNET_CONFIGURATION_load (cfgDefault, NULL);  /* load defaults only 
*/
+  ret = GNUNET_CONFIGURATION_write_diffs (cfgDefault, cfg, cfgName);
+  GNUNET_CONFIGURATION_destroy (cfgDefault);
+  return ret;
+}
+
+
+/**
  * Actual main method that sets up the configuration window.
  *
  * @param cls the main loop handle
@@ -286,8 +310,6 @@
 static void
 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct GNUNET_CONFIGURATION_Handle *cfgDefault;
-
   if (NULL == ml)
   {
     GNUNET_break (0);
@@ -295,12 +317,8 @@
   }
   GNUNET_GTK_main_loop_quit (ml);
   ml = NULL;
-  cfgDefault = GNUNET_CONFIGURATION_create ();
-  (void) GNUNET_CONFIGURATION_load (cfgDefault, NULL);  /* load defaults only 
*/
-  if (GNUNET_OK != GNUNET_CONFIGURATION_write_diffs (cfgDefault, cfg, cfgName))
+  if (GNUNET_OK != write_configuration ())
     gret = 1;
-  GNUNET_CONFIGURATION_destroy (cfgDefault);
-  GNUNET_CONFIGURATION_destroy (cfg);
   cfg = NULL;
   if (NULL != resolver)
   {
@@ -308,10 +326,42 @@
     GNUNET_OS_process_destroy (resolver);
     resolver = NULL;
   }
+  if (NULL != namestore)
+  {
+    GNUNET_break (0 == GNUNET_OS_process_kill (namestore, SIGTERM));
+    GNUNET_OS_process_destroy (namestore);
+    namestore = NULL;
+  }
 }
 
 
 /**
+ * Write configuration to dis, (re)start the namestore process and
+ * reload the namestore models.
+ * 
+ *
+ * @param cls closure (unused)
+ * @param tc scheduler context (unused)
+ */
+void
+GNUNET_SETUP_restart_namestore (void *cls,
+                               const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (GNUNET_OK != write_configuration ())
+    return; /* no point in re-starting namestore ... */
+  if (NULL != namestore)
+  {
+    GNUNET_break (0 == GNUNET_OS_process_kill (namestore, SIGTERM));
+    GNUNET_OS_process_destroy (namestore);
+    namestore = NULL;
+  }
+  /* FIXME: start namestore */
+  /* FIXME: refresh namestore model! */
+  GNUNET_break (0); // not implemented...
+}
+
+
+/**
  * Callback invoked if the application is supposed to exit.
  */
 void

Modified: gnunet-gtk/src/setup/gnunet-setup.h
===================================================================
--- gnunet-gtk/src/setup/gnunet-setup.h 2012-06-23 18:50:13 UTC (rev 22228)
+++ gnunet-gtk/src/setup/gnunet-setup.h 2012-06-23 18:57:21 UTC (rev 22229)
@@ -93,6 +93,18 @@
 
 
 /**
+ * Write configuration to dis, (re)start the namestore process and
+ * reload the namestore models.
+ * 
+ *
+ * @param cls closure (unused)
+ * @param tc scheduler context (unused)
+ */
+void
+GNUNET_SETUP_restart_namestore (void *cls,
+                               const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
  * Our configuration.
  */
 extern struct GNUNET_CONFIGURATION_Handle *cfg;




reply via email to

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