[Gpa-commits] r880 - in trunk: . src

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri May 2 15:48:42 CEST 2008


Author: werner
Date: 2008-05-02 15:48:40 +0200 (Fri, 02 May 2008)
New Revision: 880

Added:
   trunk/src/Signals
   trunk/src/gpg-stuff.c
   trunk/src/gpg-stuff.h
   trunk/src/strlist.c
   trunk/src/strlist.h
Modified:
   trunk/autogen.sh
   trunk/src/ChangeLog
   trunk/src/Makefile.am
   trunk/src/confdialog.c
   trunk/src/confdialog.h
   trunk/src/encryptdlg.c
   trunk/src/gpa.c
   trunk/src/gparecvkeydlg.c
   trunk/src/options.c
   trunk/src/options.h
   trunk/src/ownertrustdlg.c
   trunk/src/recipientdlg.c
   trunk/src/selectkeydlg.c
   trunk/src/settingsdlg.c
   trunk/src/settingsdlg.h
   trunk/src/utils.c
Log:
Fixed button order according to HIG.
Started rewrite of settings dialog.


Modified: trunk/autogen.sh
===================================================================
--- trunk/autogen.sh	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/autogen.sh	2008-05-02 13:48:40 UTC (rev 880)
@@ -85,6 +85,7 @@
 	    --with-gpgme-prefix=${w32root} \
             --with-lib-prefix=${w32root} \
             --with-libiconv-prefix=${w32root} \
+            PKG_CONFIG="$w32root/bin/pkg-config" \
             PKG_CONFIG_LIBDIR="$w32root/lib/pkgconfig" "$@"
     rc=$?
     exit $rc

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/ChangeLog	2008-05-02 13:48:40 UTC (rev 880)
@@ -1,3 +1,22 @@
+2008-05-02  Werner Koch  <wk at g10code.com>
+
+	* settingsdlg.c, settingsdlg.h: Start a rewrite.
+	* gpa.c (gpa_open_settings_dialog): Adjust for the rewrite.
+	(settings_dialog): Remove.
+	* utils.c (inet_aton) [W32]: Add replacement function.
+
+	* confdialog.c (create_dialog): Change button order and define an
+	alternative button order.
+	* encryptdlg.c (gpa_file_encrypt_dialog_constructor): Ditto.
+	* selectkeydlg.c (select_key_dlg_constructor): Ditto.
+	* recipientdlg.c (recipient_dlg_constructor): Ditto.
+	* passwddlg.c (gpa_change_passphrase_dialog_run): Ditto.
+	* ownertrustdlg.c (gpa_ownertrust_run_dialog): Ditto.
+	* keygendlg.c (gpa_key_gen_run_dialog): Ditto.
+	* gpgmetools.c (gpa_passphrase_cb): Ditto.
+	* gparecvkeydlg.c (gpa_receive_key_dialog_init): Ditto.
+	* filesigndlg.c (gpa_file_sign_dialog_constructor): Ditto.
+
 2008-05-02  Marcus Brinkmann  <marcus at g10code.de>
 
 	* gpaoperation.c (gpa_operation_write_status): Fix signal emittance.
@@ -3,4 +22,33 @@
 	(gpa_operation_class_init): Fix signature of signal STATUS.
 
+2008-04-30  Werner Koch  <wk at g10code.com>
+
+	* gpa.c (main): Try to use gpg2.
+
+2008-04-29  Werner Koch  <wk at g10code.com>
+
+	* strlist.c, strlist.h: New.  Taken from gnupg/jnlib and modified
+	for use in gpa.
+	* gpg-stuff.c, gpg-stuff.h: New. Code taken from GnuPG.
+	
+	* confdialog.c (gpa_store_configured_keyserver): Factor code out
+	to ..
+	(gpa_store_gpgconf_string): .. new.
+	(gpa_load_configured_keyserver): Factor code out to ..
+	(gpa_load_gpgconf_string): .. new.
+
+	* options.c (CHANGED_SHOW_ADVANCED_OPTION): New.
+	(gpa_options_class_init): Create new signal
+	(gpa_options_set_simplified_ui): New. 
+	(gpa_options_get_simplified_ui): New.
+	(gpa_options_save_settings, gpa_options_read_settings): Store/Load
+	new option.
+	* settingsdlg.c (ui_mode_changed_for_keyserver): Rename to ..
+	(show_advanced_option_changed_for_keyserver): .. this. 
+	(user_interface_mode_frame): Add checkbox "show advanced options".
+
+	* options (gpa_options_class_init): Factor common code out to ..
+	(make_signal): .. new.
+
 2008-04-28  Werner Koch  <wk at g10code.com>
 

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/Makefile.am	2008-05-02 13:48:40 UTC (rev 880)
@@ -117,7 +117,10 @@
 	      options.c \
 	      confdialog.h confdialog.c \
 	      gpa-marshal.c gpa-marshal.h \
+	      strlist.h strlist.c \
+	      gpg-stuff.h gpg-stuff.c \
 	      utils.c $(gpa_w32_sources)
 
 
+
 dndtest_SOURCES = dndtest.c

Added: trunk/src/Signals
===================================================================
--- trunk/src/Signals	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/Signals	2008-05-02 13:48:40 UTC (rev 880)
@@ -0,0 +1,32 @@
+                                                               -*- org -*-
+
+This file documents the use of Glib signals in GPA.
+
+** changed_ui_mode
+   Emitted if the preference setting is changed from simple to advanced
+   user interface mode and vice versa.
+*** Defined: 
+    file:options.c
+*** Connected:
+    file:keyring.c::keyring_ui_mode_changed 
+*** Emitted: 
+    file:options.c::gpa_options_set_simplified_ui
+
+** changed_show_advanced_option
+   Emitted if the preference setting for "show advanced options" is changed.
+   user interface mode and vice versa.
+*** Defined: 
+    file:options.c
+*** Connected:
+*** Emitted: 
+    file:options.c::gpa_options_set_show_advanced_options
+
+
+** changed_default_key
+
+** changed_default_keyserver
+
+** changed_view
+
+** changed_backup_generated
+

Modified: trunk/src/confdialog.c
===================================================================
--- trunk/src/confdialog.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/confdialog.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -1327,14 +1327,18 @@
 					NULL /* transient parent */,
 					0,
 					NULL);
-  gtk_dialog_add_button (GTK_DIALOG (dialog),
-			 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT); 
-  gtk_dialog_add_button (GTK_DIALOG (dialog),
-			 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY);
-  gtk_dialog_add_button (GTK_DIALOG (dialog),
- 			 _("Reset"), CUSTOM_RESPONSE_RESET);
-  gtk_dialog_add_button (GTK_DIALOG (dialog),
-			 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
+                          _("Reset"), CUSTOM_RESPONSE_RESET,
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                          NULL );
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_ACCEPT,
+                                           GTK_RESPONSE_CANCEL,
+                                           CUSTOM_RESPONSE_RESET,
+                                           GTK_RESPONSE_APPLY,
+                                           -1);
 
   g_signal_connect ((gpointer) dialog, "response",
 		    G_CALLBACK (dialog_response), NULL);
@@ -1411,10 +1415,11 @@
 
 
 
-/* Read the configured keyserver from the backend.  If none is
-   configured, return NULL.  Caller must g_free the returned value.  */
+/* Load the value of option NAME of component CNAME from the backend.
+   If none is configured, return NULL.  Caller must g_free the
+   returned value.  */
 char *
-gpa_load_configured_keyserver (void)
+gpa_load_gpgconf_string (const char *cname, const char *name)
 {
   gpg_error_t err;
   gpgme_ctx_t ctx;
@@ -1439,11 +1444,11 @@
       
   for (conf = conf_list; conf; conf = conf->next)
     {
-      if ( !strcmp (conf->name, "gpg") )
+      if ( !strcmp (conf->name, cname) )
         {
           for (opt = conf->options; opt; opt = opt->next)
             if ( !(opt->flags & GPGME_CONF_GROUP)
-                 && !strcmp (opt->name, "keyserver"))
+                 && !strcmp (opt->name, name))
               {
                 if (opt->value && opt->alt_type == GPGME_CONF_STRING)
                   retval = g_strdup (opt->value->value.string);
@@ -1459,10 +1464,11 @@
 }
 
 
-/* Save the configured keyserver from the backend.  If none is
-   configured, return NULL.  Caller must g_free the returned value.  */
+/* Set the option NAME in component "CNAME" to VALUE.  The option
+   needs to be of type string. */
 void
-gpa_store_configured_keyserver (const char *value)
+gpa_store_gpgconf_string (const char *cname, 
+                          const char *name, const char *value)
 {
   gpg_error_t err;
   gpgme_ctx_t ctx;
@@ -1492,14 +1498,13 @@
       return;
     }
 
-      
   for (conf = conf_list; conf; conf = conf->next)
     {
-      if ( !strcmp (conf->name, "gpg") )
+      if ( !strcmp (conf->name, cname) )
         {
           for (opt = conf->options; opt; opt = opt->next)
             if ( !(opt->flags & GPGME_CONF_GROUP)
-                 && !strcmp (opt->name, "keyserver"))
+                 && !strcmp (opt->name, name))
               {
                 if (opt->alt_type == GPGME_CONF_STRING
                     && !args_are_equal (arg, opt->value, opt->alt_type))
@@ -1524,3 +1529,19 @@
   gpgme_release (ctx);
 }
 
+
+/* Read the configured keyserver from the backend.  If none is
+   configured, return NULL.  Caller must g_free the returned value.  */
+char *
+gpa_load_configured_keyserver (void)
+{
+  return gpa_load_gpgconf_string ("gpg", "keyserver");
+}
+
+/* Save the configured keyserver from the backend.  If none is
+   configured, return NULL.  Caller must g_free the returned value.  */
+void
+gpa_store_configured_keyserver (const char *value)
+{
+  gpa_store_gpgconf_string ("gpg", "keyserver", value);
+}

Modified: trunk/src/confdialog.h
===================================================================
--- trunk/src/confdialog.h	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/confdialog.h	2008-05-02 13:48:40 UTC (rev 880)
@@ -23,6 +23,13 @@
 
 GtkWidget *gpa_backend_config_dialog_new (void);
 
+
+char *gpa_load_gpgconf_string (const char *cname, const char *name);
+void gpa_store_gpgconf_string (const char *cname, 
+                               const char *name, const char *value);
+
+
+
 char *gpa_load_configured_keyserver (void);
 void gpa_store_configured_keyserver (const char *value);
 

Modified: trunk/src/encryptdlg.c
===================================================================
--- trunk/src/encryptdlg.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/encryptdlg.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -136,10 +136,15 @@
   /* Initialize */
 
   /* Set up the dialog */
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Encrypt documents"));
   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+			  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 			  GTK_STOCK_OK, GTK_RESPONSE_OK,
-			  _("_Cancel"), GTK_RESPONSE_CANCEL, NULL);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Encrypt documents"));
+                          NULL);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
   gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, 
 				     FALSE);

Modified: trunk/src/gpa.c
===================================================================
--- trunk/src/gpa.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/gpa.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -77,7 +77,6 @@
 
 
 static GtkWidget *keyringeditor = NULL;
-static GtkWidget *settings_dialog = NULL;
 static GtkWidget *backend_config_dialog = NULL;
 
 
@@ -223,14 +222,7 @@
 void
 gpa_open_settings_dialog (GtkAction *action, void *data)
 {
-  if (! settings_dialog)
-    {
-      settings_dialog = gpa_settings_dialog_new ();
-      g_signal_connect (G_OBJECT (settings_dialog), "destroy",
-			G_CALLBACK (close_main_window), &settings_dialog);
-      gtk_widget_show_all (settings_dialog);
-    }
-  gtk_window_present (GTK_WINDOW (settings_dialog));
+  settings_dlg_new (data);
 }
 
 
@@ -366,7 +358,16 @@
   }
 #endif
 
+  /* Prefer gpg2 over gpg1.  Fixme: We need to test where gpg2 is
+     actually properly installed.  */
+  if (!access ("/usr/local/bin/gpg2", X_OK))
+    gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, 
+                           "/usr/local/bin/gpg2", NULL);
+  else if (!access ("/usr/bin/gpg2", X_OK))
+    gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, 
+                           "/usr/bin/gpg2", NULL);
 
+
   /* Handle command line options.  */
 
   if (args.start_only_server)

Modified: trunk/src/gparecvkeydlg.c
===================================================================
--- trunk/src/gparecvkeydlg.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/gparecvkeydlg.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -93,10 +93,13 @@
   GtkWidget *hbox;
 
   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-			  GTK_STOCK_OK,
-			  GTK_RESPONSE_OK,
-			  _("_Cancel"),
-			  GTK_RESPONSE_CANCEL, NULL);
+			  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+			  GTK_STOCK_OK, GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
   gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),5);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 

Added: trunk/src/gpg-stuff.c
===================================================================
--- trunk/src/gpg-stuff.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/gpg-stuff.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -0,0 +1,485 @@
+/* gpg-stuff.c - Code taken from GnuPG.
+ * Copyright (C) 2008 g10 Code GmbH.
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
+ *               2007, 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of GPA.
+ *
+ * GPA 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GPA 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "gpa.h"
+#include "strlist.h"
+#include "gpg-stuff.h"
+
+
+
+/* Break a string into successive option pieces.  Accepts single word
+   options and key=value argument options. */
+static char *
+optsep (char **stringp)
+{
+  char *tok, *end;
+
+  tok = *stringp;
+  if (tok)
+    {
+      end = strpbrk (tok, " ,=");
+      if (end)
+	{
+	  int sawequals = 0;
+	  char *ptr = end;
+
+	  /* what we need to do now is scan along starting with *end,
+	     If the next character we see (ignoring spaces) is an =
+	     sign, then there is an argument. */
+
+	  while (*ptr)
+	    {
+	      if (*ptr == '=')
+		sawequals = 1;
+	      else if (*ptr != ' ')
+		break;
+	      ptr++;
+	    }
+
+	  /* There is an argument, so grab that too.  At this point,
+	     ptr points to the first character of the argument. */
+	  if (sawequals)
+	    {
+	      /* Is it a quoted argument? */
+	      if (*ptr == '"')
+		{
+		  ptr++;
+		  end = strchr (ptr, '"');
+		  if (end)
+		    end++;
+		}
+	      else
+		end = strpbrk (ptr, " ,");
+	    }
+
+	  if (end && *end)
+	    {
+	      *end = '\0';
+	      *stringp = end + 1;
+	    }
+	  else
+	    *stringp = NULL;
+	}
+      else
+	*stringp = NULL;
+    }
+
+  return tok;
+}
+
+/* Breaks an option value into key and value.  Returns NULL if there
+   is no value.  Note that "string" is modified to remove the =value
+   part. */
+static char *
+argsplit(char *string)
+{
+  char *equals,*arg=NULL;
+
+  equals=strchr(string,'=');
+  if(equals)
+    {
+      char *quote,*space;
+
+      *equals='\0';
+      arg=equals+1;
+
+      /* Quoted arg? */
+      quote=strchr(arg,'"');
+      if(quote)
+	{
+	  arg=quote+1;
+
+	  quote=strchr(arg,'"');
+	  if(quote)
+	    *quote='\0';
+	}
+      else
+	{
+	  size_t spaces;
+
+	  /* Trim leading spaces off of the arg */
+	  spaces=strspn(arg," ");
+	  arg+=spaces;
+	}
+
+      /* Trim tailing spaces off of the tag */
+      space=strchr(string,' ');
+      if(space)
+	*space='\0';
+    }
+
+  return arg;
+}
+
+
+
+/* 
+   Code taken from gnupg-2.0.9/g10.keyserver.c.  Fixme: We should
+   replace it by our generic URI parser from gnupg/common/http.c. 
+*/
+
+void
+free_keyserver_spec(struct keyserver_spec *keyserver)
+{
+  xfree(keyserver->uri);
+  xfree(keyserver->scheme);
+  xfree(keyserver->auth);
+  xfree(keyserver->host);
+  xfree(keyserver->port);
+  xfree(keyserver->path);
+  xfree(keyserver->opaque);
+  free_strlist(keyserver->options);
+  xfree(keyserver);
+}
+
+static void
+add_canonical_option (char *option,strlist_t *list)
+{
+  char *arg = argsplit(option);
+
+  if (arg)
+    {
+      char *joined;
+
+      joined = xmalloc(strlen(option)+1+strlen(arg)+1);
+      /* Make a canonical name=value form with no spaces */
+      strcpy(joined,option);
+      strcat(joined,"=");
+      strcat(joined,arg);
+      append_to_strlist(list,joined);
+      xfree(joined);
+    }
+  else
+    append_to_strlist(list,option);
+}
+
+
+keyserver_spec_t
+parse_keyserver_uri(const char *string,int require_scheme,
+		    const char *configname,unsigned int configlineno)
+{
+  int assume_hkp=0;
+  struct keyserver_spec *keyserver;
+  const char *idx;
+  int count;
+  char *uri,*options;
+
+  assert(string!=NULL);
+
+  keyserver = g_malloc0 (sizeof(struct keyserver_spec));
+
+  uri=xstrdup(string);
+
+  options=strchr(uri,' ');
+  if(options)
+    {
+      char *tok;
+
+      *options='\0';
+      options++;
+
+      while((tok=optsep(&options)))
+	add_canonical_option(tok,&keyserver->options);
+    }
+
+  /* Get the scheme */
+
+  for(idx=uri,count=0;*idx && *idx!=':';idx++)
+    {
+      count++;
+
+      /* Do we see the start of an RFC-2732 ipv6 address here?  If so,
+	 there clearly isn't a scheme so get out early. */
+      if(*idx=='[')
+	{
+	  /* Was the '[' the first thing in the string?  If not, we
+	     have a mangled scheme with a [ in it so fail. */
+	  if(count==1)
+	    break;
+	  else
+	    goto fail;
+	}
+    }
+
+  if(count==0)
+    goto fail;
+
+  if(*idx=='\0' || *idx=='[')
+    {
+      if(require_scheme)
+	return NULL;
+
+      /* Assume HKP if there is no scheme */
+      assume_hkp=1;
+      keyserver->scheme=xstrdup("hkp");
+
+      keyserver->uri=xmalloc(strlen(keyserver->scheme)+3+strlen(uri)+1);
+      strcpy(keyserver->uri,keyserver->scheme);
+      strcat(keyserver->uri,"://");
+      strcat(keyserver->uri,uri);
+    }
+  else
+    {
+      int i;
+
+      keyserver->uri=xstrdup(uri);
+
+      keyserver->scheme=xmalloc(count+1);
+
+      /* Force to lowercase */
+      for(i=0;i<count;i++)
+	keyserver->scheme[i] = g_ascii_tolower(uri[i]);
+
+      keyserver->scheme[i]='\0';
+
+      /* Skip past the scheme and colon */
+      uri+=count+1;
+    }
+
+  if (!g_ascii_strcasecmp(keyserver->scheme,"x-broken-hkp"))
+    {
+      xfree(keyserver->scheme);
+      keyserver->scheme=xstrdup("hkp");
+    }
+  else if (!g_ascii_strcasecmp(keyserver->scheme,"x-hkp"))
+    {
+      /* Canonicalize this to "hkp" so it works with both the internal
+	 and external keyserver interface. */
+      xfree(keyserver->scheme);
+      keyserver->scheme=xstrdup("hkp");
+    }
+
+  if (uri[0]=='/' && uri[1]=='/' && uri[2] == '/')
+    {
+      /* Three slashes means network path with a default host name.
+         This is a hack because it does not crok all possible
+         combiantions.  We should better repalce all code bythe parser
+         from http.c.  */
+      keyserver->path = xstrdup (uri+2);
+    }
+  else if(assume_hkp || (uri[0]=='/' && uri[1]=='/'))
+    {
+      /* Two slashes means network path. */
+
+      /* Skip over the "//", if any */
+      if(!assume_hkp)
+	uri+=2;
+
+      /* Do we have userinfo auth data present? */
+      for(idx=uri,count=0;*idx && *idx!='@' && *idx!='/';idx++)
+	count++;
+
+      /* We found a @ before the slash, so that means everything
+	 before the @ is auth data. */
+      if(*idx=='@')
+	{
+	  if(count==0)
+	    goto fail;
+
+	  keyserver->auth=xmalloc(count+1);
+	  strncpy(keyserver->auth,uri,count);
+	  keyserver->auth[count]='\0';
+	  uri+=count+1;
+	}
+
+      /* Is it an RFC-2732 ipv6 [literal address] ? */
+      if(*uri=='[')
+	{
+	  for(idx=uri+1,count=1;*idx
+		&& ((isascii (*idx) && isxdigit(*idx))
+                    || *idx==':' || *idx=='.');idx++)
+	    count++;
+
+	  /* Is the ipv6 literal address terminated? */
+	  if(*idx==']')
+	    count++;
+	  else
+	    goto fail;
+	}
+      else
+	for(idx=uri,count=0;*idx && *idx!=':' && *idx!='/';idx++)
+	  count++;
+
+      if(count==0)
+	goto fail;
+
+      keyserver->host=xmalloc(count+1);
+      strncpy(keyserver->host,uri,count);
+      keyserver->host[count]='\0';
+
+      /* Skip past the host */
+      uri+=count;
+
+      if(*uri==':')
+	{
+	  /* It would seem to be reasonable to limit the range of the
+	     ports to values between 1-65535, but RFC 1738 and 1808
+	     imply there is no limit.  Of course, the real world has
+	     limits. */
+
+	  for(idx=uri+1,count=0;*idx && *idx!='/';idx++)
+	    {
+	      count++;
+
+	      /* Ports are digits only */
+	      if(!digitp(idx))
+		goto fail;
+	    }
+
+	  keyserver->port=xmalloc(count+1);
+	  strncpy(keyserver->port,uri+1,count);
+	  keyserver->port[count]='\0';
+
+	  /* Skip past the colon and port number */
+	  uri+=1+count;
+	}
+
+      /* Everything else is the path */
+      if(*uri)
+	keyserver->path=xstrdup(uri);
+      else
+	keyserver->path=xstrdup("/");
+
+      if(keyserver->path[1])
+	keyserver->flags.direct_uri=1;
+    }
+  else if(uri[0]!='/')
+    {
+      /* No slash means opaque.  Just record the opaque blob and get
+	 out. */
+      keyserver->opaque=xstrdup(uri);
+    }
+  else
+    {
+      /* One slash means absolute path.  We don't need to support that
+	 yet. */
+      goto fail;
+    }
+
+  return keyserver;
+
+ fail:
+  free_keyserver_spec(keyserver);
+
+  return NULL;
+}
+
+
+
+static void
+gpg_free_akl (akl_t akl)
+{
+  if (akl->spec)
+    free_keyserver_spec (akl->spec);
+
+  xfree (akl);
+}
+
+void
+gpg_release_akl (akl_t akl)
+{
+  while (akl)
+    {
+      akl_t tmp = akl->next;
+      gpg_free_akl (akl);
+      akl = tmp;
+    }
+}
+
+/* Takes a string OPTIONS with the argument as used for gpg'c
+   --auto-key-locate and returns an AKL list or NULL on error.  Note
+   that this function may modify OPTIONS. */
+akl_t
+gpg_parse_auto_key_locate (char *options)
+{
+  char *tok;
+  akl_t result = NULL;
+
+  while ( (tok = optsep (&options)) )
+    { 
+      akl_t akl, check;
+      akl_t last = NULL;
+      int dupe = 0;
+
+      if (!tok[0])
+	continue;
+
+      akl = xcalloc (1, sizeof (*akl));
+
+      if (!g_ascii_strcasecmp (tok, "nodefault"))
+	akl->type = AKL_NODEFAULT;
+      else if (!g_ascii_strcasecmp (tok, "local"))
+	akl->type = AKL_LOCAL;
+      else if (!g_ascii_strcasecmp (tok, "ldap"))
+	akl->type = AKL_LDAP;
+      else if (!g_ascii_strcasecmp (tok, "keyserver"))
+	akl->type = AKL_KEYSERVER;
+      else if (!g_ascii_strcasecmp (tok, "cert"))
+	akl->type = AKL_CERT;
+      else if (!g_ascii_strcasecmp (tok,"pka"))
+	akl->type = AKL_PKA;
+      else if ((akl->spec = parse_keyserver_uri (tok, 1, NULL, 0)))
+	akl->type = AKL_SPEC;
+      else
+	{
+	  gpg_free_akl (akl);
+	  gpg_release_akl (result);
+	  return NULL;
+	}
+
+      /* Check for duplicates.  We must maintain the order the user
+         gave us */
+      for (check = result; check; last=check, check=check->next)
+	{
+	  if(check->type==akl->type
+	     && (akl->type!=AKL_SPEC
+		 || (akl->type==AKL_SPEC
+		     && !strcmp(check->spec->uri,akl->spec->uri))))
+	    {
+	      dupe=1;
+	      gpg_free_akl(akl);
+	      break;
+	    }
+	}
+
+      if (!dupe)
+	{
+	  if (last)
+	    last->next = akl;
+	  else
+	    result = akl;
+	}
+    }
+
+  return result;
+}
+
+
+

Added: trunk/src/gpg-stuff.h
===================================================================
--- trunk/src/gpg-stuff.h	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/gpg-stuff.h	2008-05-02 13:48:40 UTC (rev 880)
@@ -0,0 +1,78 @@
+/* gpg-stuff.h - Code taken from GnuPG.
+ * Copyright (C) 2008 g10 Code GmbH.
+ *
+ * This file is part of GPA
+ *
+ * GPA 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GPA 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GPG_STUFF_H
+#define GPG_STUFF_H
+
+#include "strlist.h"
+
+struct keyserver_spec
+{
+  char *uri;
+  char *scheme;
+  char *auth;
+  char *host;
+  char *port;
+  char *path;
+  char *opaque;
+  strlist_t options;
+  struct
+  {
+    unsigned int direct_uri:1;
+  } flags;
+  struct keyserver_spec *next;
+};
+typedef struct keyserver_spec *keyserver_spec_t;
+
+
+void free_keyserver_spec (struct keyserver_spec *keyserver);
+keyserver_spec_t parse_keyserver_uri (const char *string,
+                                      int require_scheme,
+                                      const char *configname,
+                                      unsigned int configlineno);
+
+
+
+/* Linked list of methods to find a key.  */
+struct akl
+{
+  enum
+    {
+      AKL_NODEFAULT,
+      AKL_LOCAL,
+      AKL_CERT, 
+      AKL_PKA, 
+      AKL_LDAP,
+      AKL_KEYSERVER,
+      AKL_SPEC
+    } type;
+  struct keyserver_spec *spec;
+  struct akl *next;
+};
+typedef struct akl *akl_t;
+
+
+void gpg_release_akl (akl_t akl);
+
+/* Note: VALUE will be changed on return from the fucntion.  */
+akl_t gpg_parse_auto_key_locate (char *value);
+
+
+
+#endif /*GPG_STUFF_H*/

Modified: trunk/src/options.c
===================================================================
--- trunk/src/options.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/options.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -1,22 +1,21 @@
 /* options.h - global option declarations.
    Copyright (C) 2002 Miguel Coca.
-   Copyright (C) 2005 g10 Code GmbH.
+   Copyright (C) 2005, 2008 g10 Code GmbH.
 
-   This file is part of GPA.
+   This file is part of GPA
   
-   GPA 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 of the License, or
+   GPA 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 3 of the License, or
    (at your option) any later version.
-
-   GPA 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.
-
+  
+   GPA 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 GPA; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA  */
+   along with this program; if not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
 
@@ -47,6 +46,7 @@
 enum
 {
   CHANGED_UI_MODE,
+  CHANGED_SHOW_ADVANCED_OPTIONS,
   CHANGED_DEFAULT_KEY,
   CHANGED_DEFAULT_KEYSERVER,
   CHANGED_BACKUP_GENERATED,
@@ -85,7 +85,23 @@
   return style_type;
 }
 
+
 static void
+make_signal (int signo, GObjectClass *object_class,
+             const char *signame, size_t func_off)
+{
+  g_assert (signo >= 0 && signo < LAST_SIGNAL);
+  signals[signo] = g_signal_new (signame,
+                                 G_TYPE_FROM_CLASS (object_class),
+                                 G_SIGNAL_RUN_FIRST,
+                                 func_off,
+                                 NULL, NULL,
+                                 g_cclosure_marshal_VOID__VOID,
+                                 G_TYPE_NONE, 0);
+}
+
+
+static void
 gpa_options_class_init (GpaOptionsClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -95,55 +111,32 @@
   object_class->finalize = gpa_options_finalize;
 
   klass->changed_ui_mode = gpa_options_save_settings;
+  klass->changed_show_advanced_options = gpa_options_save_settings;
   klass->changed_default_key = gpa_options_save_settings;
   klass->changed_default_keyserver = gpa_options_save_settings;
   klass->changed_backup_generated = gpa_options_save_settings;
   klass->changed_view = gpa_options_save_settings;
 
   /* Signals */
-  signals[CHANGED_UI_MODE] =
-          g_signal_new ("changed_ui_mode",
-                        G_TYPE_FROM_CLASS (object_class),
-                        G_SIGNAL_RUN_FIRST,
-                        G_STRUCT_OFFSET (GpaOptionsClass, changed_ui_mode),
-                        NULL, NULL,
-                        g_cclosure_marshal_VOID__VOID,
-                        G_TYPE_NONE, 0);
-  signals[CHANGED_DEFAULT_KEY] =
-          g_signal_new ("changed_default_key",
-                        G_TYPE_FROM_CLASS (object_class),
-                        G_SIGNAL_RUN_FIRST,
-                        G_STRUCT_OFFSET (GpaOptionsClass, changed_default_key),
-                        NULL, NULL,
-                        g_cclosure_marshal_VOID__VOID,
-                        G_TYPE_NONE, 0);
-  signals[CHANGED_DEFAULT_KEYSERVER] =
-          g_signal_new ("changed_default_keyserver",
-                        G_TYPE_FROM_CLASS (object_class),
-                        G_SIGNAL_RUN_FIRST,
-                        G_STRUCT_OFFSET (GpaOptionsClass,
-                                         changed_default_keyserver),
-                        NULL, NULL,
-                        g_cclosure_marshal_VOID__VOID,
-                        G_TYPE_NONE, 0);
-  signals[CHANGED_VIEW] =
-          g_signal_new ("changed_view",
-                        G_TYPE_FROM_CLASS (object_class),
-                        G_SIGNAL_RUN_FIRST,
-                        G_STRUCT_OFFSET (GpaOptionsClass,
-                                         changed_view),
-                        NULL, NULL,
-                        g_cclosure_marshal_VOID__VOID,
-                        G_TYPE_NONE, 0);
-  signals[CHANGED_BACKUP_GENERATED] =
-          g_signal_new ("changed_backup_generated",
-                        G_TYPE_FROM_CLASS (object_class),
-                        G_SIGNAL_RUN_FIRST,
-                        G_STRUCT_OFFSET (GpaOptionsClass,
-                                         changed_backup_generated),
-                        NULL, NULL,
-                        g_cclosure_marshal_VOID__VOID,
-                        G_TYPE_NONE, 0);
+  make_signal (CHANGED_UI_MODE, object_class,
+               "changed_ui_mode",
+               G_STRUCT_OFFSET (GpaOptionsClass, changed_ui_mode));
+  make_signal (CHANGED_SHOW_ADVANCED_OPTIONS, object_class, 
+               "changed_show_advanced_options",
+               G_STRUCT_OFFSET (GpaOptionsClass,
+                                changed_show_advanced_options));
+  make_signal (CHANGED_DEFAULT_KEY, object_class,
+                "changed_default_key",
+                G_STRUCT_OFFSET (GpaOptionsClass, changed_default_key));
+  make_signal (CHANGED_DEFAULT_KEYSERVER, object_class,
+               "changed_default_keyserver",
+               G_STRUCT_OFFSET (GpaOptionsClass, changed_default_keyserver));
+  make_signal (CHANGED_VIEW, object_class,
+               "changed_view",
+               G_STRUCT_OFFSET (GpaOptionsClass, changed_view));
+  make_signal (CHANGED_BACKUP_GENERATED, object_class,
+               "changed_backup_generated",
+               G_STRUCT_OFFSET (GpaOptionsClass, changed_backup_generated));
 }
 
 static void
@@ -151,6 +144,7 @@
 {
   options->options_file = NULL;
   options->simplified_ui = TRUE;
+  options->show_advanced_options = FALSE;
   options->backup_generated = FALSE;
   options->default_key = NULL;
   options->default_key_fpr = NULL;
@@ -232,6 +226,20 @@
   return options->simplified_ui;
 }
 
+/* Set whether the preference dialog shows the advanced options. */
+void
+gpa_options_set_show_advanced_options (GpaOptions *options, gboolean value)
+{
+  options->show_advanced_options = value;
+  g_signal_emit (options, signals[CHANGED_SHOW_ADVANCED_OPTIONS], 0);
+}
+
+gboolean
+gpa_options_get_show_advanced_options (GpaOptions *options)
+{
+  return options->show_advanced_options;
+}
+
 /* Choose the default key */
 void
 gpa_options_set_default_key (GpaOptions *options, gpgme_key_t key)
@@ -418,6 +426,10 @@
         {
           fprintf (options_file, "%s\n", "advanced-ui");
         }
+      if (options->show_advanced_options)
+        {
+          fprintf (options_file, "%s\n", "show-advanced-options");
+        }
       if (options->detailed_view)
         {
           fprintf (options_file, "%s\n", "detailed-view");
@@ -512,6 +524,10 @@
                 {
                   options->simplified_ui = FALSE;
                 }
+              else if (g_str_equal (next_word, "show-advanced-options"))
+                {
+                  options->show_advanced_options = TRUE;
+                }
               else if (g_str_equal (next_word, "detailed-view"))
                 {
                   options->detailed_view = TRUE;

Modified: trunk/src/options.h
===================================================================
--- trunk/src/options.h	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/options.h	2008-05-02 13:48:40 UTC (rev 880)
@@ -42,6 +42,7 @@
   gchar *options_file;
 
   gboolean simplified_ui;
+  gboolean show_advanced_options;
   gboolean backup_generated;
 
   gpgme_key_t default_key;
@@ -56,6 +57,7 @@
 
   /* Signal handlers */
   void (*changed_ui_mode) (GpaOptions *options);
+  void (*changed_show_advanced_options) (GpaOptions *options);
   void (*changed_default_key) (GpaOptions *options);
   void (*changed_default_keyserver) (GpaOptions *options);
   void (*changed_backup_generated) (GpaOptions *options);
@@ -79,6 +81,11 @@
 void gpa_options_set_simplified_ui (GpaOptions *options, gboolean value);
 gboolean gpa_options_get_simplified_ui (GpaOptions *options);
 
+/* Set whether the preference dialog shows the advanced options. */
+void gpa_options_set_show_advanced_options (GpaOptions *options,
+                                            gboolean value);
+gboolean gpa_options_get_show_advanced_options (GpaOptions *options);
+
 /* Choose the default key */
 void gpa_options_set_default_key (GpaOptions *options, gpgme_key_t key);
 gpgme_key_t gpa_options_get_default_key (GpaOptions *options);

Modified: trunk/src/ownertrustdlg.c
===================================================================
--- trunk/src/ownertrustdlg.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/ownertrustdlg.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -103,14 +103,15 @@
 
   /* Create the dialog */
 
-  dialog = gtk_dialog_new_with_buttons (_("Change key ownertrust"), 
-                                        GTK_WINDOW(parent),
-                                        GTK_DIALOG_MODAL,
-                                        GTK_STOCK_OK,
-                                        GTK_RESPONSE_OK,
-                                        _("_Cancel"),
-                                        GTK_RESPONSE_CANCEL,
-                                        NULL);
+  dialog = gtk_dialog_new_with_buttons
+    (_("Change key ownertrust"), GTK_WINDOW(parent), GTK_DIALOG_MODAL,
+     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+     GTK_STOCK_OK, GTK_RESPONSE_OK,
+     NULL);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
 

Modified: trunk/src/recipientdlg.c
===================================================================
--- trunk/src/recipientdlg.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/recipientdlg.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -927,12 +927,16 @@
 				      construct_properties);
   dialog = RECIPIENT_DLG (object);
 
-
+  gtk_window_set_title (GTK_WINDOW (dialog),
+                        _("Select keys for recipients"));
   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+			  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 			  GTK_STOCK_OK, GTK_RESPONSE_OK,
-			  _("_Cancel"), GTK_RESPONSE_CANCEL, NULL);
-  gtk_window_set_title (GTK_WINDOW (dialog),
-                        _("Select keys for recipients"));
+                          NULL);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
   gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, 
 				     FALSE);

Modified: trunk/src/selectkeydlg.c
===================================================================
--- trunk/src/selectkeydlg.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/selectkeydlg.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -175,13 +175,16 @@
 				      n_construct_properties,
 				      construct_properties);
   dialog = SELECT_KEY_DLG (object);
-
-
+  gtk_window_set_title (GTK_WINDOW (dialog),
+                        _("Select a key"));
   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+			  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 			  GTK_STOCK_OK, GTK_RESPONSE_OK,
-			  _("_Cancel"), GTK_RESPONSE_CANCEL, NULL);
-  gtk_window_set_title (GTK_WINDOW (dialog),
-                        _("Select a key"));
+                          NULL);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
   gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, 
 				     FALSE);

Modified: trunk/src/settingsdlg.c
===================================================================
--- trunk/src/settingsdlg.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/settingsdlg.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -15,23 +15,164 @@
    GNU General Public License for more details.
   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301 USA.  */
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
+
+/* Violation of GNOME standards: Cancel does not revert a previous
+   apply.  Excvept for the UI mode, we do not auto-apply or syntax
+   check after focus change.  The rationale for this is that:
+
+     * gpgconf operations are expensive.
+
+     * Some fields depend on each other and without a proper framework
+       for doing plausibility checks it is hard to get it right.
+
+*/
+
+
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+/* Required for the IP address check.  */
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#else /*!HAVE_W32_SYSTEM*/
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+#endif /*!HAVE_W32_SYSTEM*/
+
+
 #include "gpa.h"
-#include "settingsdlg.h"
 #include "gpakeyselector.h"
 #include "keyserver.h"
+#include "gtktools.h"
+#include "confdialog.h"
+#include "gpg-stuff.h"
 
 #include "settingsdlg.h"
 
+/* Object and class definition.  */
+struct _SettingsDlg 
+{
+  GtkDialog parent;
+  
+  GtkWidget *foo;
 
+};
+
+struct _SettingsDlgClass 
+{
+  GtkDialogClass parent_class;
+
+};
+
+static GObjectClass *parent_class;
+
+/* We only want one instance of the settings dialog at a time.  Thus
+   we use this variable to keep track of a created instance.  */
+static SettingsDlg *the_settings_dialog;
+
+
+
+/* Identifiers for our properties. */
+enum 
+  {
+    PROP_0,
+    PROP_WINDOW,
+  };
+
+
+
+/* A table with common and useful --auto-key-locate combinations. The
+   first entry "local" is a made-up which indicates that no
+   --auto-key-locate is active.  "Custom" ist used for all settings
+   which can't be mapped to this table and is also the last entry in
+   the table indicating the end of the table. */
+static struct { 
+  const char *list;
+  const char *text; 
+} akl_table[] = {
+  { "l",   N_("Local")},
+  { "lk",  N_("Local, Keyserver")},
+  { "lp",  N_("Local, PKA")},
+  { "lpk", N_("Local, PKA, Keyserver")},
+  { "lkp", N_("Local, Keyserver, PKA")},
+  { "lD",  N_("Local, kDNS")},
+  { "lDk", N_("Local, kDNS, Keyserver")},
+  { "np",  N_("PKA")},
+  { "nD",  N_("kDNS")},
+  { NULL,  N_("Custom")},
+};
+
+
+
 
+/* 
+   User interface section. 
+ */
+static void
+advanced_mode_toggled (GtkToggleButton *button, gpointer user_data)
+{
+  gpa_options_set_simplified_ui (gpa_options_get_instance (), 
+                                 !gtk_toggle_button_get_active (button));
+}
+
+static void
+show_advanced_options_toggled (GtkToggleButton *button, gpointer user_data)
+{
+  gpa_options_set_show_advanced_options
+    (gpa_options_get_instance (), gtk_toggle_button_get_active (button));
+}
+
+
+static GtkWidget *
+user_interface_mode_frame (SettingsDlg *dialog)
+{
+  GtkWidget *frame;
+  GtkWidget *label;
+  GtkWidget *frame_vbox;
+  GtkWidget *button, *button2;
+
+  /* Build UI.  */
+  frame = gtk_frame_new (NULL);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+  label = gtk_label_new (_("<b>User interface</b>"));
+  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+  gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+
+  frame_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (frame), frame_vbox);
+
+  button = gtk_check_button_new_with_mnemonic (_("use _advanced mode"));
+  gtk_container_add (GTK_CONTAINER (frame_vbox), button);
+
+  button2 = gtk_check_button_new_with_mnemonic (_("show advanced _options"));
+  gtk_container_add (GTK_CONTAINER (frame_vbox), button2);
+
+
+  /* Select default value.  */
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
+                                !gpa_options_get_simplified_ui 
+                                (gpa_options_get_instance ()));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button2), 
+                                !!gpa_options_get_show_advanced_options 
+                                (gpa_options_get_instance ()));
+
+  /* Connect signals.  */
+  g_signal_connect (G_OBJECT (button), "toggled",
+                    G_CALLBACK (advanced_mode_toggled), NULL);
+  g_signal_connect (G_OBJECT (button2), "toggled",
+                    G_CALLBACK (show_advanced_options_toggled), NULL);
+
+  
+  return frame;
+}
+
+
+
+
 /* Default key section.  */
 static void
 key_selected_cb (GtkTreeSelection *treeselection, gpointer user_data)
@@ -47,7 +188,7 @@
 
 
 static GtkWidget *
-default_key_frame (void)
+default_key_frame (SettingsDlg *dialog)
 {
   GtkWidget *frame;
   GtkWidget *label;
@@ -84,37 +225,31 @@
 }
 
 
-/* Signal handler for the "changed_ui_mode" signal.  */
+/* Signal handler for the "changed_show_advanced_options" signal.  */
 static void
-ui_mode_changed_for_keyserver (GpaOptions *options, gpointer param)
+show_advanced_options_changed_for_keyserver (GpaOptions *options,
+                                             gpointer param)
 {
   GtkWidget *keyserver_frame = param;
 
-  if (gpa_options_get_simplified_ui (options))
+  if (gpa_options_get_show_advanced_options (options))
+    gtk_widget_show_all (GTK_WIDGET(keyserver_frame));
+  else
     gtk_widget_hide_all (GTK_WIDGET(keyserver_frame));
-  else
-    gtk_widget_show_all (GTK_WIDGET(keyserver_frame));
 }
 
-/* Default keyserver section.  */
-static gboolean
-keyserver_selected_cb (GtkWidget *combo, GdkEvent *event, gpointer user_data)
-{
-  gchar *text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (combo));
 
-  if (text != NULL && *text != '\0')
-    gpa_options_set_default_keyserver (gpa_options_get_instance (), text);
-
-  return FALSE;
-}
-
-
 static void
-selected_from_list_cb (GtkComboBox *combo, gpointer user_data)
+keyserver_selected_from_list_cb (GtkComboBox *combo, gpointer user_data)
 {
   /* Consider the text entry activated.  */
   if (gtk_combo_box_get_active (combo) != -1)
-    keyserver_selected_cb (GTK_WIDGET (combo), NULL, NULL);
+    {
+      /* FIXME: Update only on apply.  */
+      char *text = gtk_combo_box_get_active_text (combo);
+      if (text && *text)
+        gpa_options_set_default_keyserver (gpa_options_get_instance (), text);
+    }
 }
 
 
@@ -129,7 +264,7 @@
 
 
 static GtkWidget *
-default_keyserver_frame (void)
+default_keyserver_frame (SettingsDlg *dialog)
 {
   GtkWidget *frame;
   GtkWidget *label;
@@ -154,101 +289,432 @@
                       gpa_options_get_default_keyserver
 		      (gpa_options_get_instance ()));
 
-  /* Set default visibility.  */
-  ui_mode_changed_for_keyserver (gpa_options_get_instance (), frame);
-
-  /* Connect signals.  Try to follow instant-apply principle.  */
-  g_signal_connect_swapped (G_OBJECT (gtk_bin_get_child (GTK_BIN (combo))),
-			    "focus-out-event",
-			    G_CALLBACK (keyserver_selected_cb), combo);
+  /* Connect signals.  */
   g_signal_connect (G_OBJECT (combo),
-		    "changed", G_CALLBACK (selected_from_list_cb), NULL);
+		    "changed",
+                    G_CALLBACK (keyserver_selected_from_list_cb), NULL);
 
   g_signal_connect (G_OBJECT (gpa_options_get_instance ()),
-		    "changed_ui_mode",
-                    G_CALLBACK (ui_mode_changed_for_keyserver), frame);
-  
+		    "changed_show_advanced_options",
+                    G_CALLBACK (show_advanced_options_changed_for_keyserver), 
+                    frame);
 
   return frame;
 }
 
 
-/* User interface section.  */
+/* Auto Key Locate section.  */
+/* Signal handler for the "changed_show_advanced_options" signal.  */
 static void
-advanced_mode_toggled (GtkToggleButton *button, gpointer user_data)
+show_advanced_options_changed_for_akl (GpaOptions *options,
+                                       gpointer param)
 {
-  gpa_options_set_simplified_ui (gpa_options_get_instance (), 
-                                 !gtk_toggle_button_get_active (button));
+  GtkWidget *akl_frame = param;
+
+  if (gpa_options_get_show_advanced_options (options))
+    gtk_widget_show_all (GTK_WIDGET(akl_frame));
+  else
+    gtk_widget_hide_all (GTK_WIDGET(akl_frame));
 }
 
+
+static void
+akl_method_changed_cb (GtkComboBox *combo, gpointer user_data)
+{
+  GtkWidget *label = user_data;
+  int idx;
+
+  idx =  gtk_combo_box_get_active (combo);
+  if (idx < 0 || idx > DIM(akl_table))
+    return;
+
+  /* Enable the kdns Server entry if needed.  */
+  gtk_widget_set_sensitive (label, (akl_table[idx].list
+                                    && strchr (akl_table[idx].list, 'D')) );
+  
+}
+
+static void
+akl_kdnsaddr_changed_cb (GtkEntry *entry, gpointer user_data)
+{
+  const char *addr;
+  struct in_addr binaddr;
+
+  (void)user_data;
+
+  if (!GTK_WIDGET_IS_SENSITIVE (entry))
+    return;
+  
+  addr = gtk_entry_get_text (entry);
+  g_message ("IP-address is '%s'", addr? addr : "[none]");
+  if (!addr || !*addr || !inet_aton (addr, &binaddr) )
+    {
+      gpa_window_error ("You need to enter a valid IPv4 address.",
+                        GTK_WIDGET (entry));
+      return;
+    }
+
+  g_message ("IP-address is '%s' is valid", addr);
+  /* Fixme: Contruct the new --auto-key-locate option.  */
+
+}
+
+
+static void
+parse_akl (GtkWidget *combo, GtkWidget *kdns_addr, GtkWidget *label)
+{
+  akl_t akllist, akl;
+  char *akloption = gpa_load_gpgconf_string ("gpg", "auto-key-locate");
+  char list[10];
+  int listidx = 0;
+  int idx;
+  
+  if (!akloption)
+    {
+      /* Select the first entry ("Local").  */
+      gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); 
+      /* Set kDNS server to empty.  */
+      gtk_entry_set_text (GTK_ENTRY (kdns_addr), "");
+      gtk_widget_set_sensitive (label, FALSE);
+      return;
+    }
+
+  /* Well, lets parse it.  */
+  akllist = gpg_parse_auto_key_locate (akloption);
+  g_free (akloption);
+  for (akl = akllist; akl && listidx < sizeof list - 1; akl = akl->next)
+    {
+      keyserver_spec_t k = akl->spec;
+
+      switch (akl->type )
+        {
+        case AKL_NODEFAULT:
+          list[listidx++] = 'n';
+          break;
+        case AKL_LOCAL:
+          list[listidx++] = 'l';
+          break;
+        case AKL_CERT:
+          list[listidx++] = 'c';
+          break;
+        case AKL_PKA:
+          list[listidx++] = 'p';
+          break;
+        case AKL_LDAP:
+          list[listidx++] = 'L';
+          break;
+        case AKL_KEYSERVER:
+          list[listidx++] = 'k';
+          break;
+        case AKL_SPEC:
+          if ( (k = akl->spec)
+               && k->scheme && !strcmp (k->scheme, "kdns")
+               && !k->auth
+               && k->host
+               && !k->port
+               && k->path && !strcmp (k->path, "/?at=_kdnscert&usevc=1")
+               && !k->opaque
+               && !k->options)
+            {
+              gtk_entry_set_text (GTK_ENTRY (kdns_addr), k->host);
+              list[listidx++] = 'D';
+            }
+          else
+            list[listidx++] = '?';
+          break;
+            
+        default:
+          list[listidx++] = '?';
+          break;
+        }
+    }
+  list[listidx] = 0;
+  gpg_release_akl (akllist);
+  fprintf (stderr, "akl list: %s\n", list);
+
+  for (idx=0; akl_table[idx].list; idx++)
+    if (!strcmp (akl_table[idx].list, list))
+      break;
+  /* (The last entry of tghe tale is the one used for no-match.) */
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo), idx); 
+  /* Enable the kdns Server entry if one is defined.  For ease of
+     implementation we have already put the server address into the
+     entry field even if though there might be no match.  */
+  gtk_widget_set_sensitive (label, 
+                            (akl_table[idx].list && strchr (list, 'D')));
+
+}
+
+
 static GtkWidget *
-user_interface_mode_frame (void)
+auto_key_locate_frame (SettingsDlg *dialog)
 {
+  const char *tooltip;
   GtkWidget *frame;
   GtkWidget *label;
+  GtkWidget *frame_vbox;
+  GtkWidget *combo;
+  GtkWidget *entry;
   GtkWidget *hbox;
-  GtkWidget *button;
+  int xpad, ypad;
+  int idx;
 
   /* Build UI.  */
   frame = gtk_frame_new (NULL);
   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
-  label = gtk_label_new (_("<b>User interface</b>"));
+  label = gtk_label_new_with_mnemonic (_("<b>Auto key _locate</b>"));
   gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
   gtk_frame_set_label_widget (GTK_FRAME (frame), label);
 
-  button = gtk_check_button_new_with_mnemonic (_("use _advanced mode"));
-  gtk_container_add (GTK_CONTAINER (frame), button);
+  frame_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (frame), frame_vbox);
 
+  /* The method selection.  */
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (frame_vbox), hbox);
+  tooltip = _("The list of methods to locate keys via an email address.\n"
+              "All given methods are used in turn until a matching "
+              "key is found.  The supported methods are:\n"
+              " Local\n"
+              "   - Use the local keyring.\n"
+              " Keyserver\n"
+              "   - Use the default keyserver.\n"
+              " PKA\n"
+              "   - Use the Public Key Association.\n"
+              " kDNS\n"
+              "   - Use kDNS with the nameserver below.\n"
+              " Custom\n"
+              "   - Configured in the backend dialog.\n");
+  gpa_add_tooltip (hbox, tooltip);
 
-  /* Select default value.  */
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
-                                !gpa_options_get_simplified_ui 
-                                (gpa_options_get_instance ()));
+  label = gtk_label_new (_("Method:"));
+  gtk_misc_get_padding (GTK_MISC (label), &xpad, &ypad);
+  xpad += 5;
+  gtk_misc_set_padding (GTK_MISC (label), xpad, ypad);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
+  combo = gtk_combo_box_new_text ();
+  gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
+
+  idx=0;
+  do
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _(akl_table[idx].text));
+  while (akl_table[idx++].list);
+
+  /* The kDNS server.  */
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (frame_vbox), hbox);
+  tooltip = _("The IP address of the nameserver used for the kDNS method.");
+  gpa_add_tooltip (hbox, tooltip);
+  label = gtk_label_new (_("kDNS Server:"));
+  gtk_misc_get_padding (GTK_MISC (label), &xpad, &ypad);
+  xpad += 5;
+  gtk_misc_set_padding (GTK_MISC (label), xpad, ypad);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+  entry = gtk_entry_new ();
+  gtk_entry_set_max_length (GTK_ENTRY(entry), 3+1+3+1+3+1+3);
+  gtk_entry_set_width_chars (GTK_ENTRY(entry), 3+1+3+1+3+1+3);
+  gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
+
+  parse_akl (combo, entry, hbox);
+  g_signal_connect (G_OBJECT (combo),
+		    "changed", G_CALLBACK (akl_method_changed_cb), hbox);
+  g_signal_connect (G_OBJECT (entry),
+		    "changed", G_CALLBACK (akl_kdnsaddr_changed_cb), NULL);
+
+
   /* Connect signals.  */
-  g_signal_connect (G_OBJECT (button), "toggled",
-                    G_CALLBACK (advanced_mode_toggled), NULL);
+  g_signal_connect (G_OBJECT (gpa_options_get_instance ()),
+		    "changed_show_advanced_options",
+                    G_CALLBACK (show_advanced_options_changed_for_akl), 
+                    frame);
 
   
   return frame;
 }
 
+/* Save all settings, return 0 on success.  */
+static int
+save_settings (GtkDialog *dialog)
+{
+
+
+  return FALSE;
+}
+
+
+/* Handle the response signal.  */
+static void
+dialog_response (GtkDialog *dialog, gint response)
+{
+  switch (response)
+    {
+    case GTK_RESPONSE_OK:
+      if (save_settings (dialog))
+        return;
+      break;
+
+    case GTK_RESPONSE_APPLY:
+      if (save_settings (dialog))
+        return;
+      /* Fixme: Reload configuration.  */
+      
+      return; /* Do not close.  */
+
+    default:
+      break;
+    }
+
+  gtk_widget_destroy (GTK_WIDGET(dialog));
+}
+
 
-/* Create a new settings dialog and return it.  The dialog is shown
-   but not run.  */
-GtkWidget *
-gpa_settings_dialog_new (void)
+/************************************************************ 
+ ******************   Object Management  ********************
+ ************************************************************/
+
+
+static void
+settings_dlg_finalize (GObject *object)
+{  
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+settings_dlg_init (SettingsDlg *dialog)
 {
-  GtkWidget *dialog;
+}
+
+
+static GObject*
+settings_dlg_constructor (GType type, guint n_construct_properties,
+                          GObjectConstructParam *construct_properties)
+{
+  GObject *object;
+  SettingsDlg *dialog;
   GtkWidget *frame, *keyserver_frame;
 
-  dialog = gtk_dialog_new_with_buttons (_("Settings"), NULL, 0,
-                                        _("_Close"),
-                                        GTK_RESPONSE_CLOSE, NULL);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
-  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
-  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 5);
+  object = parent_class->constructor (type,
+				      n_construct_properties,
+				      construct_properties);
+  dialog = SETTINGS_DLG (object);
+  gtk_window_set_title (GTK_WINDOW (dialog),
+			_("GNU Privacy Assistant - Settings"));
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                          GTK_STOCK_OK, GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           GTK_RESPONSE_APPLY,
+                                           -1);
 
   /* The UI mode section.  */
-  frame = keyserver_frame = user_interface_mode_frame ();
-  gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame);
+  frame = user_interface_mode_frame (dialog);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame,
+                      FALSE, FALSE, 0);
               
   /* The default key section.  */
-  frame = default_key_frame ();
+  frame = default_key_frame (dialog);
   gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame);
 
   /* The default keyserver section.  */
-  frame = default_keyserver_frame ();
-  gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame);
+  frame = keyserver_frame = default_keyserver_frame (dialog);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame,
+                      FALSE, FALSE, 0);
 
-  /* Close the dialog when asked to.  */
-  g_signal_connect_swapped (GTK_OBJECT (dialog), 
-                            "response", 
-                            G_CALLBACK (gtk_widget_destroy),
-                            GTK_OBJECT (dialog));
+  /* The auto key locate section.  */
+  frame = auto_key_locate_frame (dialog);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame,
+                      FALSE, FALSE, 0);
 
-  /* Don't run the dialog here: leave that to gtk_main.  */
-  gtk_widget_show_all (GTK_WIDGET (dialog));
+  /* Connect the response signal.  */
+  g_signal_connect (GTK_OBJECT (dialog), "response", 
+                    G_CALLBACK (dialog_response), NULL);
 
-  return dialog;
+  /* Show all windows and hide those we don't want. */
+  gtk_widget_show_all (GTK_WIDGET(dialog));
+  if (!gpa_options_get_show_advanced_options (gpa_options_get_instance ()))
+    gtk_widget_hide_all (GTK_WIDGET(keyserver_frame));
+
+  return object;
 }
+
+
+static void
+settings_dlg_class_init (SettingsDlgClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  
+  parent_class = g_type_class_peek_parent (klass);
+  
+  object_class->constructor  = settings_dlg_constructor;
+  object_class->finalize     = settings_dlg_finalize;
+
+}
+
+
+GType
+settings_dlg_get_type (void)
+{
+  static GType this_type;
+  
+  if (!this_type)
+    {
+      static const GTypeInfo this_info =
+	{
+	  sizeof (SettingsDlgClass),
+	  (GBaseInitFunc) NULL,
+	  (GBaseFinalizeFunc) NULL,
+	  (GClassInitFunc) settings_dlg_class_init,
+	  NULL, /* class_finalize */
+	  NULL, /* class_data */
+
+	  sizeof (SettingsDlg),
+	  0,    /* n_preallocs */
+	  (GInstanceInitFunc) settings_dlg_init,
+	};
+      
+      this_type = g_type_register_static (GTK_TYPE_DIALOG,
+                                          "SettingsDlg",
+                                          &this_info, 0);
+    }
+  
+  return this_type;
+}
+
+
+
+/************************************************************ 
+ **********************  Public API  ************************
+ ************************************************************/
+
+/* Show the preference dialog and it create it if not yet done.  */
+void
+settings_dlg_new (GtkWidget *parent)
+{
+  g_return_if_fail (GTK_IS_WINDOW (parent));
+
+  if (!the_settings_dialog)
+    {
+      the_settings_dialog = g_object_new (SETTINGS_DLG_TYPE, NULL);
+      g_signal_connect (the_settings_dialog,
+                        "destroy",
+                        G_CALLBACK (gtk_widget_destroyed),
+                        &the_settings_dialog);
+
+    }
+
+  if (GTK_WINDOW (parent) 
+      != gtk_window_get_transient_for (GTK_WINDOW (the_settings_dialog)))
+    gtk_window_set_transient_for (GTK_WINDOW (the_settings_dialog),
+                                  GTK_WINDOW (parent));
+  
+  gtk_window_present (GTK_WINDOW (the_settings_dialog));
+}
+

Modified: trunk/src/settingsdlg.h
===================================================================
--- trunk/src/settingsdlg.h	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/settingsdlg.h	2008-05-02 13:48:40 UTC (rev 880)
@@ -1,5 +1,4 @@
 /* settingsdlg.c - The GNU Privacy Assistant
-   Copyright (C) 2002, Miguel Coca
    Copyright (C) 2008 g10 Code GmbH.
 
    This file is part of GPA.
@@ -20,8 +19,47 @@
 #ifndef SETTINGSDLG_H
 #define SETTINGSDLG_H
 
-/* Create a new settings dialog and return it.  The dialog is shown
-   but not run.  */
-GtkWidget *gpa_settings_dialog_new (void);
 
-#endif
+/* Definitions to define the object.  */
+#define SETTINGS_DLG_TYPE \
+          (settings_dlg_get_type ())
+
+#define SETTINGS_DLG(obj) \
+          (G_TYPE_CHECK_INSTANCE_CAST \
+            ((obj), SETTINGS_DLG_TYPE,\
+              SettingsDlg))
+
+#define SETTINGS_DLG_CLASS(klass) \
+          (G_TYPE_CHECK_CLASS_CAST \
+            ((klass), SETTINGS_DLG_TYPE, \
+              SettingsDlgClass))
+
+#define IS_SETTINGS_DLG(obj) \
+          (G_TYPE_CHECK_INSTANCE_TYPE \
+            ((obj), SETTINGS_DLG_TYPE))
+
+#define IS_SETTINGS_DLG_CLASS(klass) \
+          (G_TYPE_CHECK_CLASS_TYPE \
+            ((klass), SETTINGS_DLG_TYPE))
+
+#define SETTINGS_DLG_GET_CLASS(obj) \
+          (G_TYPE_INSTANCE_GET_CLASS \
+            ((obj), SETTINGS_DLG_TYPE, \
+              SettingsDlgClass))
+
+typedef struct _SettingsDlg SettingsDlg;
+typedef struct _SettingsDlgClass SettingsDlgClass;
+
+
+GType settings_dlg_get_type (void) G_GNUC_CONST;
+
+
+/************************************
+ ************ Public API ************
+ ************************************/
+
+/* Create and show the settings dialog.  */
+void settings_dlg_new (GtkWidget *parent);
+
+
+#endif /*SETTINGSDLG_H*/

Added: trunk/src/strlist.c
===================================================================
--- trunk/src/strlist.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/strlist.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -0,0 +1,176 @@
+/* strlist.c -  string helpers
+ * Copyright (C) 2008 g10 Code GmbH.
+ * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "gpa.h"
+#include "strlist.h"
+
+void
+free_strlist( strlist_t sl )
+{
+    strlist_t sl2;
+
+    for(; sl; sl = sl2 ) {
+	sl2 = sl->next;
+	g_free(sl);
+    }
+}
+
+
+strlist_t
+add_to_strlist( strlist_t *list, const char *string )
+{
+    strlist_t sl;
+
+    sl = g_malloc ( sizeof *sl + strlen(string));
+    sl->flags = 0;
+    strcpy(sl->d, string);
+    sl->next = *list;
+    *list = sl;
+    return sl;
+}
+
+
+/* Same as add_to_strlist() but if is_utf8 is *not* set, a conversion
+   to UTF-8 is done.  */
+#if 0
+#ifdef JNLIB_NEED_UTF8CONV
+strlist_t
+add_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
+{
+  strlist_t sl;
+  
+  if (is_utf8)
+    sl = add_to_strlist( list, string );
+  else 
+    {
+      char *p = native_to_utf8( string );
+      sl = add_to_strlist( list, p );
+      jnlib_free ( p );
+    }
+  return sl;
+}
+#endif /* JNLIB_NEED_UTF8CONV*/
+#endif 
+
+strlist_t
+append_to_strlist( strlist_t *list, const char *string )
+{
+    strlist_t r, sl;
+
+    sl = g_malloc( sizeof *sl + strlen(string));
+    sl->flags = 0;
+    strcpy(sl->d, string);
+    sl->next = NULL;
+    if( !*list )
+	*list = sl;
+    else {
+	for( r = *list; r->next; r = r->next )
+	    ;
+	r->next = sl;
+    }
+    return sl;
+}
+
+
+#if 0
+#ifdef JNLIB_NEED_UTF8CONV
+strlist_t
+append_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
+{
+  strlist_t sl;
+    
+  if( is_utf8 )
+    sl = append_to_strlist( list, string );
+  else
+    {
+      char *p = native_to_utf8 (string);
+      sl = append_to_strlist( list, p );
+      jnlib_free( p );
+    }
+  return sl;
+}
+#endif /* JNLIB_NEED_UTF8CONV */
+#endif
+
+/* Return a copy of LIST. */
+strlist_t
+strlist_copy (strlist_t list)
+{
+  strlist_t newlist = NULL, sl, *last;
+
+  last = &newlist;
+  for (; list; list = list->next)
+    {
+      sl = g_malloc (sizeof *sl + strlen (list->d));
+      sl->flags = list->flags;
+      strcpy(sl->d, list->d);
+      sl->next = NULL;
+      *last = sl;
+      last = &sl;
+    }
+  return newlist;
+}
+
+
+
+strlist_t
+strlist_prev( strlist_t head, strlist_t node )
+{
+    strlist_t n;
+
+    for(n=NULL; head && head != node; head = head->next )
+	n = head;
+    return n;
+}
+
+strlist_t
+strlist_last( strlist_t node )
+{
+    if( node )
+	for( ; node->next ; node = node->next )
+	    ;
+    return node;
+}
+
+
+char *
+strlist_pop (strlist_t *list)
+{
+  char *str=NULL;
+  strlist_t sl=*list;
+
+  if(sl)
+    {
+      str = g_malloc ( strlen (sl->d) + 1 );
+      strcpy (str,sl->d);
+
+      *list=sl->next;
+      g_free(sl);
+    }
+
+  return str;
+}
+

Added: trunk/src/strlist.h
===================================================================
--- trunk/src/strlist.h	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/strlist.h	2008-05-02 13:48:40 UTC (rev 880)
@@ -0,0 +1,45 @@
+/* strlist.h
+ *	Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GPA_STRLIST_H
+#define GPA_STRLIST_H
+
+struct string_list 
+{
+  struct string_list *next;
+  unsigned int flags;
+  char d[1];
+};
+typedef struct string_list *strlist_t;
+
+void    free_strlist (strlist_t sl);
+strlist_t add_to_strlist (strlist_t *list, const char *string);
+
+strlist_t append_to_strlist (strlist_t *list, const char *string);
+
+strlist_t strlist_copy (strlist_t list);
+
+strlist_t strlist_prev (strlist_t head, strlist_t node);
+strlist_t strlist_last (strlist_t node);
+char * strlist_pop (strlist_t *list);
+
+#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0)
+
+
+#endif /*GPA_STRLIST_H*/

Modified: trunk/src/utils.c
===================================================================
--- trunk/src/utils.c	2008-05-02 13:05:26 UTC (rev 879)
+++ trunk/src/utils.c	2008-05-02 13:48:40 UTC (rev 880)
@@ -1,5 +1,5 @@
-/* utilis.c -  Utility functions for GPA.
- * Copyright (C) 2007 g10 Code GmbH
+/* utils.c -  Utility functions for GPA.
+ * Copyright (C) 2008 g10 Code GmbH
  *
  * This file is part of GPA
  *
@@ -25,6 +25,9 @@
 #include <string.h>
 #include <errno.h>
 #include <glib.h>
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#endif /*HAVE_W32_SYSTEM*/
 
 #include "gpa.h"
 
@@ -102,3 +105,28 @@
   return fd;
 #endif
 }
+
+
+#ifdef HAVE_W32_SYSTEM
+int 
+inet_aton (const char *cp, struct in_addr *inp)
+{
+  if (!cp || !*cp || !inp)
+    {
+      errno = EINVAL;
+      return 0; 
+    }
+  
+  if (!strcmp(cp, "255.255.255.255"))
+    {
+      /*  Although this is a valid address, the old inet_addr function
+          is not able to handle it.  */
+        inp->s_addr = INADDR_NONE;
+        return 1;
+    }
+  
+  inp->s_addr = inet_addr (cp);
+  return (inp->s_addr != INADDR_NONE);
+}
+#endif /*HAVE_W32_SYSTEM*/
+



More information about the Gpa-commits mailing list