changeset 122:76e2b58a9440

2003-4-5 Brian Masney <masneyb@gftp.org> * lib/config_file.c lib/options.h lib/gftp.h lib/rfc959.c lib/rfc2068.c lib/ssh.c - added new internal configuration interface. Rather than having a global variable for each option, I have a global hash table (gftp_global_options_htable) that I can look up option names by name using gftp_lookup_global_option(). I also an options hash associated with a request structure, so I will be able to call gftp_lookup_request_option(). I will be able to override options with bookmarks or while transfers are in progress very easily now. Also, all options no longer have to appear in config_file.c, the per protocol options can appear inside their own file * lib/gftp.h lib/bookmarks.c lib/local.c lib/rfc959.c lib/rfc2068.c - remove set_data_type and protocol name from struct gftp_request * lib/rfc959.c - renamed all firewall_* variables to ftp_proxy_* in the config file * lib/gftp.h lib/protocols.c lib/rfc959.c - renamed all GFTP_TYPE_* vars to GFTP_DIRTYPE_* * lib/gftp.h - removed ascii field and renamed the node pointer to user_data in struct gftp_file. In gftp_request, removed any setting that is now stored in the global/local hash tables. Added register_module() pointer that will be called whenever the protocol is first loaded into gftp * lib/rfc959.c src/text/gftp-text.c - moved the ascii/binary translation to rfc959.c. Also, moved any instance of automatically setting the data type to rfc959.c as well. * lib/misc.c lib/sshv2.c - moved all ssh functions from misc.c to sshv2.c. I had these origionally in misc.c because I used to have 2 different SSH protocols * lib/protocols.c src/text/gftp-text.c - added gftp_calc_kbs() to protocols.c. This no longer needs to be in the different ports * src/text/gftp-text.c - read/write options based on new configuration interface * Use new configuration interface in all source files * Updated copyright dates on all source files * Note: GTK+ port is completely broken at the moment. I'll upload those changes whenever I get them done
author masneyb
date Sat, 05 Apr 2003 16:30:45 +0000
parents 1b41e6945e9d
children dd65e3fbd058
files lib/bookmark.c lib/cache.c lib/config_file.c lib/gftp.h lib/local.c lib/misc.c lib/options.h lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c src/text/gftp-text.c src/text/gftp-text.h
diffstat 13 files changed, 2120 insertions(+), 1979 deletions(-) [+]
line wrap: on
line diff
--- a/lib/bookmark.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/bookmark.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  bookmark.c - functions for connecting to a site via a bookmark           */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -46,6 +46,12 @@
 }
 
 
+void 
+bookmark_register_module (void)
+{
+}
+
+
 void
 bookmark_init (gftp_request * request)
 {
@@ -64,7 +70,6 @@
   request->end_transfer = NULL;
   request->list_files = NULL;
   request->get_next_file = NULL;
-  request->set_data_type = NULL;
   request->get_file_size = NULL;
   request->chdir = NULL;
   request->rmdir = NULL;
@@ -76,7 +81,6 @@
   request->site = NULL;
   request->parse_url = bookmark_parse_url;
   request->url_prefix = "bookmark";
-  request->protocol_name = "Bookmark";
   request->need_hostport = 0;
   request->need_userpass = 0;
   request->use_threads = 0;
--- a/lib/cache.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/cache.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  cache.c - contains the cache routines                                    */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
--- a/lib/config_file.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/config_file.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  config_file.c - config file routines                                     */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -20,511 +20,100 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
-static void write_comment 			( FILE * fd, 
-						  const char *comment );
-static int parse_args 				( char *str, 
-						  int numargs, 
-						  int lineno, 
-						  char **first, 
-						  ... );
-
-gftp_config_vars config_file_vars[] = 
+void
+gftp_add_bookmark (gftp_bookmarks_var * newentry)
 {
-  {"", N_("General"), (void *) 0x1, CONFIG_NOTEBOOK, "", NULL, GFTP_PORT_GTK},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"email", N_("Email address:"), &emailaddr, CONFIG_CHARTEXT, 
-	N_("Enter your email address here"), NULL, GFTP_PORT_ALL},
-  {"view_program", N_("View program:"), &view_program, CONFIG_CHARTEXT,
-	N_("The default program used to view files. If this is blank, the internal file viewer will be used"), NULL, GFTP_PORT_ALL},
-  {"edit_program", N_("Edit program:"), &edit_program, CONFIG_CHARTEXT,
-	N_("The default program used to edit files."), NULL, GFTP_PORT_GTK},
-  {"startup_directory", N_("Startup Directory:"), &startup_directory, CONFIG_CHARTEXT,
-        N_("The default directory gFTP will go to on startup"), NULL, GFTP_PORT_ALL},
-  {"max_log_window_size", N_("Max Log Window Size:"), &max_log_window_size, CONFIG_UINTTEXT,
-        N_("The maximum size of the log window in bytes for the GTK+ port"), NULL, GFTP_PORT_GTK},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"append_transfers", N_("Append file transfers"), &append_file_transfers,
-        CONFIG_CHECKBOX,
-        N_("Append new file transfers onto existing ones"), NULL, GFTP_PORT_GTK},
-  {"one_transfer", N_("Do one transfer at a time"),  &do_one_transfer_at_a_time, CONFIG_CHECKBOX, 
-	N_("Do only one transfer at a time?"), NULL, GFTP_PORT_GTK}, 
-  {"overwrite_default", N_("Overwrite by Default"), &overwrite_by_default, CONFIG_CHECKBOX,
-        N_("Overwrite files by default or set to resume file transfers"), NULL, GFTP_PORT_GTK},
-  {"refresh_files", N_("Refresh after each file transfer"), &refresh_files, CONFIG_CHECKBOX, 
-	N_("Refresh the listbox after each file is transfered"), NULL, GFTP_PORT_GTK},
-  {"sort_dirs_first", N_("Sort directories first"), &sort_dirs_first, CONFIG_CHECKBOX, 
-	N_("Put the directories first then the files"), NULL, GFTP_PORT_ALL},
-  {"start_transfers", N_("Start file transfers"), &start_file_transfers, CONFIG_CHECKBOX, 
-	N_("Automatically start the file transfers when they get queued?"), NULL, GFTP_PORT_GTK},
-  {"show_hidden_files", N_("Show hidden files"), &show_hidden_files, CONFIG_CHECKBOX, 
-	N_("Show hidden files in the listboxes"), NULL, GFTP_PORT_ALL},
-  
-  {"", N_("Network"), (void *) 0x1, CONFIG_NOTEBOOK, "", NULL, GFTP_PORT_GTK},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"network_timeout", N_("Network timeout:"), &network_timeout, CONFIG_INTTEXT, 
-	N_("The timeout waiting for network input/output. This is NOT an idle timeout."), NULL, GFTP_PORT_ALL},
-  {"retries", N_("Connect retries:"), &retries, CONFIG_INTTEXT, 
-	N_("The number of auto-retries to do. Set this to 0 to retry indefinately"), NULL, GFTP_PORT_ALL},
-  {"sleep_time", N_("Retry sleep time:"), &sleep_time, CONFIG_INTTEXT, 
-	N_("The number of seconds to wait between retries"), NULL, GFTP_PORT_ALL},
-  {"maxkbs", N_("Max KB/S:"), &maxkbs, CONFIG_FLOATTEXT, 
-	N_("The maximum KB/s a file transfer can get. (Set to 0 to disable)"), NULL, GFTP_PORT_ALL},
-  {"", N_("Default Protocol"), (void *) 0x1, CONFIG_COMBO, "DP", NULL, GFTP_PORT_GTK},
-  {"default_protocol", N_("Default Protocol"), &default_protocol, 
-        CONFIG_CHARTEXT, N_("This specifies the default protocol to use"), NULL, 0},
-
-  {"", N_("FTP"), (void *) 0x1, CONFIG_NOTEBOOK, "", NULL, GFTP_PORT_GTK},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"firewall_host", N_("Proxy hostname:"), &firewall_host, CONFIG_CHARTEXT,
-	N_("Firewall hostname"), NULL, GFTP_PORT_ALL},
-  {"firewall_port", N_("Proxy port:"), &firewall_port, CONFIG_INTTEXT,
-	N_("Port to connect to on the firewall"), NULL, GFTP_PORT_ALL},
-  {"firewall_username", N_("Proxy username:"), &firewall_username,
-	CONFIG_CHARTEXT, N_("Your firewall username"), NULL, GFTP_PORT_ALL},
-  {"firewall_password", N_("Proxy password:"), &firewall_password, 
-	CONFIG_CHARPASS, N_("Your firewall password"), NULL, GFTP_PORT_ALL},
-  {"firewall_account", N_("Proxy account:"), &firewall_account, CONFIG_CHARTEXT, 
-	N_("Your firewall account (optional)"), NULL, GFTP_PORT_ALL},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-
-  {"passive_transfer", N_("Passive file transfers"), &passive_transfer, CONFIG_CHECKBOX, 
-	N_("Send PASV command or PORT command for data transfers"), NULL, GFTP_PORT_ALL},
-  {"resolve_symlinks", N_("Resolve Remote Symlinks (LIST -L)"), &resolve_symlinks, CONFIG_CHECKBOX, 
-	N_("If you disable this feature, then gFTP will only send LIST to the remote server instead of LIST -L"), NULL, GFTP_PORT_ALL},
-
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"", N_("Proxy server type"), (void *) 0x1, CONFIG_COMBO, "PS", NULL, GFTP_PORT_GTK},
-  {"proxy_config", N_("Proxy config"), &proxy_config, CONFIG_TEXT,
-	N_("This specifies how your proxy server expects us to log in"), NULL, GFTP_PORT_GTK},
-  {"", N_("%pu = proxy user"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%hu = host user"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%pp = proxy pass"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%hp = host pass"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%ph = proxy host"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%hh = host"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%po = proxy port"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%ho = host port"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%pa = proxy account"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-  {"", N_("%ha = host account"), (void *) 0x1, CONFIG_LABEL, "", NULL, 0},
-
-  {"", N_("HTTP"), (void *) 0x1, CONFIG_NOTEBOOK, "", NULL, GFTP_PORT_GTK},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"http_proxy_host", N_("Proxy hostname:"), &http_proxy_host, CONFIG_CHARTEXT,
-	N_("Firewall hostname"), NULL, GFTP_PORT_ALL},
-  {"http_proxy_port", N_("Proxy port:"), &http_proxy_port, CONFIG_INTTEXT, 
-	N_("Port to connect to on the firewall"), NULL, GFTP_PORT_ALL},
-  {"http_proxy_username", N_("Proxy username:"), &http_proxy_username, 
-	CONFIG_CHARTEXT, N_("Your firewall username"), NULL, GFTP_PORT_ALL},
-  {"http_proxy_password", N_("Proxy password:"), &http_proxy_password, 
-	CONFIG_CHARPASS, N_("Your firewall password"), NULL, GFTP_PORT_ALL},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"use_http11", N_("Use HTTP/1.1"), &use_http11, CONFIG_CHECKBOX,
-	N_("Do you want to use HTTP/1.1 or HTTP/1.0"), NULL, GFTP_PORT_ALL},
+  gftp_bookmarks_var * preventry, * folderentry, * endentry;
+  char *curpos;
 
-  {"", N_("SSH"), (void *) 0x1, CONFIG_NOTEBOOK, "", NULL, GFTP_PORT_GTK},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"ssh_prog_name", N_("SSH Prog Name:"), &ssh_prog_name, CONFIG_CHARTEXT,
-	N_("The path to the SSH executable"), NULL, GFTP_PORT_ALL},
-  {"ssh_extra_params", N_("SSH Extra Params:"), &ssh_extra_params, 
-        CONFIG_CHARTEXT, N_("Extra parameters to pass to the SSH program"), NULL, GFTP_PORT_ALL},
-  {"ssh2_sftp_path", N_("SSH2 sftp-server path:"), &ssh2_sftp_path,
-	CONFIG_CHARTEXT, N_("Default remote SSH2 sftp-server path"), NULL, GFTP_PORT_ALL},
-  {"", "", (void *) 0x1, CONFIG_TABLE, "", NULL, GFTP_PORT_GTK},
-  {"ssh_need_userpass", N_("Need SSH User/Pass"), &ssh_need_userpass, CONFIG_CHECKBOX, 
-        N_("Require a username/password for SSH connections"), NULL, GFTP_PORT_ALL},
-  {"ssh_use_askpass", N_("Use ssh-askpass util"), &ssh_use_askpass, CONFIG_CHECKBOX, 
-        N_("Use the ssh-askpass utility to grab the users password"), NULL, GFTP_PORT_GTK},
-  {"sshv2_use_sftp_subsys", N_("Use SSH2 SFTP subsys"), &sshv2_use_sftp_subsys, CONFIG_CHECKBOX, 
-        N_("Call ssh with the -s sftp flag. This is helpful because you won't have to know the remote path to the remote sftp-server"), NULL, GFTP_PORT_GTK},
-
-  {"list_dblclk_action", "", &listbox_dblclick_action, CONFIG_HIDEINT, 
-	N_("This defines what will happen when you double click a file in the file listboxes. 0=View file 1=Edit file 2=Transfer file"), NULL, 0},
-  {"listbox_local_width", "", &listbox_local_width, CONFIG_HIDEINT, 
-	N_("The default width of the local files listbox"), NULL, 0},
-  {"listbox_remote_width", "", &listbox_remote_width, CONFIG_HIDEINT,
-	N_("The default width of the remote files listbox"), NULL, 0},
-  {"listbox_file_height", "", &listbox_file_height, CONFIG_HIDEINT,
-	N_("The default height of the local/remote files listboxes"), NULL, 0},
-  {"transfer_height", "", &transfer_height, CONFIG_HIDEINT,
-	N_("The default height of the transfer listbox"), NULL, 0},
-  {"log_height", "", &log_height, CONFIG_HIDEINT,
-	N_("The default height of the logging window"), NULL, 0},
-  {"file_trans_column", "", &file_trans_column, CONFIG_HIDEINT,
-	N_("The width of the filename column in the transfer window. Set this to 0 to have this column automagically resize."), NULL, 0},
-  {"local_sortcol", "", &local_sortcol, CONFIG_INTTEXT, 
-	N_("The default column to sort by"), NULL, GFTP_PORT_TEXT},
-  {"local_sortasds", "", &local_sortasds, CONFIG_INTTEXT,
-	N_("Sort ascending or descending"), NULL, GFTP_PORT_TEXT},
-  {"remote_sortcol", "", &remote_sortcol, CONFIG_INTTEXT,
-	N_("The default column to sort by"), NULL, GFTP_PORT_TEXT},
-  {"remote_sortasds", "", &remote_sortasds, CONFIG_INTTEXT,
-	N_("Sort ascending or descending"), NULL, GFTP_PORT_TEXT},
-  {"local_file_width", "", &local_columns[0], CONFIG_HIDEINT,
-	N_("The width of the filename column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"local_size_width", "", &local_columns[1], CONFIG_HIDEINT,
-	N_("The width of the size column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"local_user_width", "", &local_columns[2], CONFIG_HIDEINT,
-	N_("The width of the user column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"local_group_width", "", &local_columns[3], CONFIG_HIDEINT,
-	N_("The width of the group column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"local_date_width", "", &local_columns[4], CONFIG_HIDEINT,
-	N_("The width of the date column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"local_attribs_width", "", &local_columns[5], CONFIG_HIDEINT,
-	N_("The width of the attribs column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"remote_file_width", "", &remote_columns[0], CONFIG_HIDEINT,
-	N_("The width of the filename column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"remote_size_width", "", &remote_columns[1], CONFIG_HIDEINT,
-	N_("The width of the size column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"remote_user_width", "", &remote_columns[2], CONFIG_HIDEINT,
-	N_("The width of the user column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"remote_group_width", "", &remote_columns[3], CONFIG_HIDEINT,
-	N_("The width of the group column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"remote_date_width", "", &remote_columns[4], CONFIG_HIDEINT,
-	N_("The width of the date column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"remote_attribs_width", "", &remote_columns[5], CONFIG_HIDEINT,
-	N_("The width of the attribs column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), NULL, 0},
-  {"send_color", "", &send_color, CONFIG_COLOR,
-        N_("The color of the commands that are sent to the server"), NULL, 0},
-  {"recv_color", "", &recv_color, CONFIG_COLOR,
-        N_("The color of the commands that are received from the server"), NULL, 0},
-  {"error_color", "", &error_color, CONFIG_COLOR,
-        N_("The color of the error messages"), NULL, 0},
-  {"misc_color", "", &misc_color, CONFIG_COLOR,
-        N_("The color of the rest of the log messages"), NULL, 0},
-  {NULL, NULL, NULL, 0, "", NULL, 0}
-};
-
-
-void
-gftp_read_config_file (char **argv, int get_xpms)
-{
-  char *tempstr, *temp1str, *curpos, *endpos, buf[255], *str, *red, *green, 
-       *blue;
-  gftp_file_extensions * tempext;
-  gftp_bookmarks * newentry;
-  gftp_proxy_hosts * host;
-  unsigned int nums[4];
-  struct hostent *hent;
-  struct utsname unme;
-  gftp_color * color;
-  struct passwd *pw;
-  FILE *conffile;
-  uid_t my_uid;
-  gid_t my_gid;
-  int line, i;
-  size_t len;
-  void *ptr;
-
-  memset (&send_color, 0, sizeof (send_color));
-  memset (&recv_color, 0, sizeof (recv_color));
-  memset (&error_color, 0, sizeof (error_color));
-  memset (&misc_color, 0, sizeof (misc_color));
-  send_color.green = 0x8600;
-  recv_color.blue = 0xffff;
-  error_color.red = 0xffff;
-  misc_color.red = 0xffff;
-
-  line = 0;
-  bookmarks = g_malloc0 (sizeof (*bookmarks));
-  bookmarks->isfolder = 1;
-  bookmarks->path = g_malloc0 (1);
-  bookmarks_htable = g_hash_table_new (string_hash_function, string_hash_compare);
-  config_htable = g_hash_table_new (string_hash_function, string_hash_compare);
-
-  if ((tempstr = expand_path (CONFIG_FILE)) == NULL)
+  if (!newentry->protocol)
     {
-      printf (_("gFTP Error: Bad config file name %s\n"), CONFIG_FILE);
-      exit (1);
+      newentry->protocol = g_malloc (4);
+      strcpy (newentry->protocol, "FTP");
     }
 
-  if (access (tempstr, F_OK) == -1)
-    {
-      temp1str = expand_path (BASE_CONF_DIR);
-      if (access (temp1str, F_OK) == -1)
-	{
-	  if (mkdir (temp1str, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
-	    {
-	      printf (_("gFTP Error: Could not make directory %s: %s\n"),
-		      temp1str, g_strerror (errno));
-	      exit (1);
-	    }
-	}
-      g_free (temp1str);
-
-      temp1str = g_strdup_printf ("%s/gftprc", SHARE_DIR);
-      if (access (temp1str, F_OK) == -1)
-	{
-	  printf (_("gFTP Error: Cannot find master config file %s\n"),
-		  temp1str);
-	  printf (_("Did you do a make install?\n"));
-	  exit (1);
-	}
-      copyfile (temp1str, tempstr);
-      g_free (temp1str);
-    }
-
-  if ((conffile = fopen (tempstr, "r")) == NULL)
-    {
-      printf (_("gFTP Error: Cannot open config file %s: %s\n"), CONFIG_FILE,
-	      g_strerror (errno));
-      exit (1);
-    }
-  g_free (tempstr);
- 
-  for (i = 0; config_file_vars[i].var != NULL; i++)
-    {
-      g_hash_table_insert (config_htable, config_file_vars[i].key, 
-                           GINT_TO_POINTER(i));
-    } 
-
-  while (fgets (buf, sizeof (buf), conffile))
+  /* We have to create the folders. For example, if we have 
+     Debian Sites/Debian, we have to create a Debian Sites entry */
+  preventry = gftp_bookmarks;
+  if (preventry->children != NULL)
     {
-      len = strlen (buf);
-      if (len > 0 && buf[len - 1] == '\n')
-	buf[--len] = '\0';
-      if (len > 0 && buf[len - 1] == '\r')
-	buf[--len] = '\0';
-      line++;
-
-      if (*buf == '#' || *buf == '\0')
-        continue;
-
-      if ((curpos = strchr (buf, '=')) != NULL)
-        *curpos = '\0';
-
-      if ((ptr = g_hash_table_lookup (config_htable, buf)) != NULL)
-        {
-          i = GPOINTER_TO_INT(ptr);
-          curpos = buf + strlen (buf) + 1;
-          if (config_file_vars[i].type == CONFIG_CHARTEXT ||
-              config_file_vars[i].type == CONFIG_CHARPASS ||
-              config_file_vars[i].type == CONFIG_TEXT)
-            {
-              *(char **) config_file_vars[i].var = g_malloc (strlen (curpos) + 1);
-              strcpy (*(char **) config_file_vars[i].var, curpos);
-            }
-          else if (config_file_vars[i].type == CONFIG_FLOATTEXT)
-            *(double *) config_file_vars[i].var = strtod (curpos, NULL);
-          else if (config_file_vars[i].type == CONFIG_COLOR)
-            {
-              color = config_file_vars[i].var;
-              parse_args (curpos, 3, line, &red, &green, &blue);
-              color->red = strtol (red, NULL, 16);
-              color->green = strtol (green, NULL, 16);
-              color->blue = strtol (blue, NULL, 16);
-              g_free (red);
-              g_free (green);
-              g_free (blue);
-            }
-          else
-            *(int *) config_file_vars[i].var = strtol (curpos, NULL, 10);
-	}
-      else if (strcmp (buf, "host") == 0)
+      endentry = preventry->children;
+      while (endentry->next != NULL)
+	endentry = endentry->next;
+    }
+  else
+    endentry = NULL;
+  curpos = newentry->path;
+  while ((curpos = strchr (curpos, '/')) != NULL)
+    {
+      *curpos = '\0';
+      /* See if we already made this folder */
+      if ((folderentry = (gftp_bookmarks_var *)
+	   g_hash_table_lookup (gftp_bookmarks_htable, newentry->path)) == NULL)
 	{
-          /* This is just here for compatibility with old versions of gftp */
-	  curpos = buf + 5;
-	  while (*curpos == '/')
-	    curpos++;
-	  newentry = g_malloc0 (sizeof (*newentry));
-	  newentry->isfolder = 0;
-	  parse_args (curpos, 8, line, &newentry->path, &newentry->hostname,
-		      &temp1str, &newentry->remote_dir, &newentry->user,
-		      &newentry->pass, &tempstr, &newentry->acct);
-	  newentry->port = strtol (temp1str, NULL, 10);
-	  g_free (temp1str);
-	  newentry->save_password = *newentry->pass != '\0';
-	  add_to_bookmark (newentry);
-	}
-      else if (strcmp (buf, "dont_use_proxy") == 0)
-	{
-	  curpos = buf + 15;
-	  host = g_malloc0 (sizeof (*host));
-	  if ((tempstr = strchr (curpos, '/')) == NULL)
-	    {
-	      host->domain = g_malloc (strlen (curpos) + 1);
-	      strcpy (host->domain, curpos);
-	    }
+	  /* Allocate the individual folder. We have to do this for the edit 
+	     bookmarks feature */
+	  folderentry = g_malloc0 (sizeof (*folderentry));
+	  folderentry->path = g_malloc (strlen (newentry->path) + 1);
+	  strcpy (folderentry->path, newentry->path);
+	  folderentry->prev = preventry;
+	  folderentry->isfolder = 1;
+	  g_hash_table_insert (gftp_bookmarks_htable, folderentry->path,
+			       folderentry);
+	  if (preventry->children == NULL)
+	    preventry->children = folderentry;
 	  else
-	    {
-	      *tempstr = '\0';
-	      sscanf (curpos, "%u.%u.%u.%u", &nums[0], &nums[1], &nums[2],
-		      &nums[3]);
-	      host->ipv4_network_address =
-		nums[0] << 24 | nums[1] << 16 | nums[2] << 8 | nums[3];
-
-	      if (strchr (tempstr + 1, '.') == NULL)
-		host->ipv4_netmask =
-		    0xffffffff << (32 - strtol (tempstr + 1, NULL, 10));
-	      else
-		{
-		  sscanf (tempstr + 1, "%u.%u.%u.%u", &nums[0], &nums[1],
-			  &nums[2], &nums[3]);
-		  host->ipv4_netmask =
-		    nums[0] << 24 | nums[1] << 16 | nums[2] << 8 | nums[3];
-		}
-	    }
-	  proxy_hosts = g_list_append (proxy_hosts, host);
-	}
-      else if (strcmp (buf, "ext") == 0)
-	{
-          if (get_xpms)
-            {
-	      curpos = buf + 4;
-	      tempext = g_malloc (sizeof (*tempext));
-	      parse_args (curpos, 4, line, &tempext->ext, &tempext->filename,
-	  	          &tempext->ascii_binary, &tempext->view_program);
- 
-	      if ((tempstr = get_xpm_path (tempext->filename, 1)) != NULL)
-	        g_free (tempstr);
-
-	      tempext->stlen = strlen (tempext->ext);
-              registered_exts = g_list_append (registered_exts, tempext);
-            }
-	}
-      else if (strcmp (buf, "localhistory") == 0)
-	{
-	  curpos = buf + 13;
-	  str = g_malloc (strlen (curpos) + 1);
-	  strcpy (str, curpos);
-	  localhistory = g_list_append (localhistory, str);
-	  localhistlen++;
-	}
-      else if (strcmp (buf, "remotehistory") == 0)
-	{
-	  curpos = buf + 14;
-	  str = g_malloc (strlen (curpos) + 1);
-	  strcpy (str, curpos);
-	  remotehistory = g_list_append (remotehistory, str);
-	  remotehistlen++;
-	}
-      else if (strcmp (buf, "hosthistory") == 0)
-	{
-	  curpos = buf + 12;
-	  str = g_malloc (strlen (curpos) + 1);
-	  strcpy (str, curpos);
-	  host_history = g_list_append (host_history, str);
-	  host_len++;
-	}
-      else if (strcmp (buf, "porthistory") == 0)
-	{
-	  curpos = buf + 12;
-	  str = g_malloc (strlen (curpos) + 1);
-	  strcpy (str, curpos);
-	  port_history = g_list_append (port_history, str);
-	  port_len++;
-	}
-      else if (strcmp (buf, "userhistory") == 0)
-	{
-	  curpos = buf + 12;
-	  str = g_malloc (strlen (curpos) + 1);
-	  strcpy (str, curpos);
-	  user_history = g_list_append (user_history, str);
-	  user_len++;
+	    endentry->next = folderentry;
+	  preventry = folderentry;
+	  endentry = NULL;
 	}
       else
 	{
-	  printf (_("gFTP Warning: Skipping line %d in config file: %s\n"),
-                  line, buf);
+	  preventry = folderentry;
+	  if (preventry->children != NULL)
+	    {
+	      endentry = preventry->children;
+	      while (endentry->next != NULL)
+		endentry = endentry->next;
+	    }
+	  else
+	    endentry = NULL;
 	}
-    }
-
-  if (default_protocol == NULL)
-    {
-      default_protocol = g_malloc (4);
-      strcpy (default_protocol, "FTP");
-    }
-
-  for (i = 0; gftp_protocols[i].name; i++)
-    {
-      if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
-        break;
-    }
-
-  if (gftp_protocols[i].name == NULL)
-    {
-      printf (_("gFTP Error: Default protocol %s is not a valid protocol\n"), default_protocol);
-      exit (1);
-    }
-
-  if ((tempstr = expand_path (LOG_FILE)) == NULL)
-    {
-      printf (_("gFTP Error: Bad log file name %s\n"), LOG_FILE);
-      exit (1);
+      *curpos = '/';
+      curpos++;
     }
 
-  if ((logfd = fopen (tempstr, "w")) == NULL)
-    {
-      printf (_("gFTP Warning: Cannot open %s for writing: %s\n"),
-              tempstr, g_strerror (errno));
-    }
-  g_free (tempstr);
-
-  gftp_read_bookmarks ();
-
-  if (ssh_extra_params != NULL)
+  /* Get the parent node */
+  if ((curpos = strrchr (newentry->path, '/')) == NULL)
+    preventry = gftp_bookmarks;
+  else
     {
-      num_ssh_extra_params = 0;
-      curpos = ssh_extra_params;
-      while ((endpos = strchr (curpos, ' ')) != NULL)
-        {
-          *endpos = '\0';
-          num_ssh_extra_params++;
-          ssh_extra_params_list = g_realloc (ssh_extra_params_list,
-                                             (num_ssh_extra_params + 1) * 
-                                             sizeof (char *));
-          ssh_extra_params_list[num_ssh_extra_params - 1] = g_strdup (curpos);
-          ssh_extra_params_list[num_ssh_extra_params] = NULL;
-          *endpos = ' ';
-          curpos = endpos + 1;
-        }
-
-      if (*curpos != '\0')
-        {
-          num_ssh_extra_params++;
-          ssh_extra_params_list = g_realloc (ssh_extra_params_list,
-                                             (num_ssh_extra_params + 1) * 
-                                             sizeof (char *));
-          ssh_extra_params_list[num_ssh_extra_params - 1] = g_strdup (curpos);
-          ssh_extra_params_list[num_ssh_extra_params] = NULL;
-        }
+      *curpos = '\0';
+      preventry = (gftp_bookmarks_var *)
+	g_hash_table_lookup (gftp_bookmarks_htable, newentry->path);
+      *curpos = '/';
     }
 
-  make_nonnull (&proxy_config);
-  make_nonnull (&firewall_host);
-  make_nonnull (&firewall_username);
-  make_nonnull (&firewall_password);
-  make_nonnull (&firewall_account);
-  make_nonnull (&http_proxy_host);
-  make_nonnull (&http_proxy_username);
-  make_nonnull (&http_proxy_password);
-  make_nonnull (&view_program);
-  make_nonnull (&edit_program);
-
-  my_uid = geteuid ();
-  my_gid = getegid ();
-  pw = getpwuid (my_uid);
-  if (emailaddr == NULL || *emailaddr == '\0')
+  if (preventry->children != NULL)
     {
-      /* If there is no email address specified, then we'll just use the
-         currentuser@currenthost */
-      if (emailaddr)
-        g_free (emailaddr);
-      uname (&unme);
-      hent = gethostbyname (unme.nodename);
-      if (strchr (unme.nodename, '.') == NULL && hent != NULL)
-        emailaddr = g_strconcat (pw->pw_name, "@", hent->h_name, NULL);
-      else
-        emailaddr = g_strconcat (pw->pw_name, "@", unme.nodename, NULL);
-      gftp_write_config_file ();
+      endentry = preventry->children;
+      while (endentry->next != NULL)
+	endentry = endentry->next;
+      endentry->next = newentry;
     }
+  else
+    preventry->children = newentry;
+  newentry->prev = preventry;
+  newentry->next = NULL;
+  g_hash_table_insert (gftp_bookmarks_htable, newentry->path, newentry);
 }
 
 
-void
+static void
 gftp_read_bookmarks (void)
 {
   char *tempstr, *temp1str, buf[255], *curpos;
-  gftp_bookmarks *newentry;
+  gftp_bookmarks_var * newentry;
   FILE *bmfile;
   size_t len;
   int line;
@@ -575,7 +164,7 @@
 	  newentry->path = g_malloc (len);
 	  strcpy (newentry->path, buf + 1);
 	  newentry->isfolder = 0;
-	  add_to_bookmark (newentry);
+	  gftp_add_bookmark (newentry);
 	}
       else if (strncmp (buf, "hostname", 8) == 0 && newentry)
 	{
@@ -651,329 +240,6 @@
 }
 
 
-void
-add_to_bookmark (gftp_bookmarks * newentry)
-{
-  gftp_bookmarks *preventry, *folderentry, *endentry;
-  char *curpos;
-
-  if (!newentry->protocol)
-    {
-      newentry->protocol = g_malloc (4);
-      strcpy (newentry->protocol, "FTP");
-    }
-
-  /* We have to create the folders. For example, if we have 
-     Debian Sites/Debian, we have to create a Debian Sites entry */
-  preventry = bookmarks;
-  if (preventry->children != NULL)
-    {
-      endentry = preventry->children;
-      while (endentry->next != NULL)
-	endentry = endentry->next;
-    }
-  else
-    endentry = NULL;
-  curpos = newentry->path;
-  while ((curpos = strchr (curpos, '/')) != NULL)
-    {
-      *curpos = '\0';
-      /* See if we already made this folder */
-      if ((folderentry = (gftp_bookmarks *)
-	   g_hash_table_lookup (bookmarks_htable, newentry->path)) == NULL)
-	{
-	  /* Allocate the individual folder. We have to do this for the edit 
-	     bookmarks feature */
-	  folderentry = g_malloc0 (sizeof (*folderentry));
-	  folderentry->path = g_malloc (strlen (newentry->path) + 1);
-	  strcpy (folderentry->path, newentry->path);
-	  folderentry->prev = preventry;
-	  folderentry->isfolder = 1;
-	  g_hash_table_insert (bookmarks_htable, folderentry->path,
-			       folderentry);
-	  if (preventry->children == NULL)
-	    preventry->children = folderentry;
-	  else
-	    endentry->next = folderentry;
-	  preventry = folderentry;
-	  endentry = NULL;
-	}
-      else
-	{
-	  preventry = folderentry;
-	  if (preventry->children != NULL)
-	    {
-	      endentry = preventry->children;
-	      while (endentry->next != NULL)
-		endentry = endentry->next;
-	    }
-	  else
-	    endentry = NULL;
-	}
-      *curpos = '/';
-      curpos++;
-    }
-
-  /* Get the parent node */
-  if ((curpos = strrchr (newentry->path, '/')) == NULL)
-    preventry = bookmarks;
-  else
-    {
-      *curpos = '\0';
-      preventry = (gftp_bookmarks *)
-	g_hash_table_lookup (bookmarks_htable, newentry->path);
-      *curpos = '/';
-    }
-
-  if (preventry->children != NULL)
-    {
-      endentry = preventry->children;
-      while (endentry->next != NULL)
-	endentry = endentry->next;
-      endentry->next = newentry;
-    }
-  else
-    preventry->children = newentry;
-  newentry->prev = preventry;
-  newentry->next = NULL;
-  g_hash_table_insert (bookmarks_htable, newentry->path, newentry);
-}
-
-
-void
-gftp_write_config_file (void)
-{
-  char *hdr, *proxyhdr, *exthdr, *histhdr;
-  gftp_file_extensions *tempext;
-  gftp_proxy_hosts *hosts;
-  gftp_color *color;
-  GList *templist;
-  FILE *conffile;
-  char *tempstr;
-  int pos;
-
-  hdr = N_("Config file for gFTP. Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>. Warning: Any comments that you add to this file WILL be overwritten. If a entry has a (*) in it's comment, you can't change it inside gFTP");
-  proxyhdr = N_("This section specifies which hosts are on the local subnet and won't need to go out the proxy server (if available). Syntax: dont_use_proxy=.domain or dont_use_proxy=network number/netmask");
-  exthdr = N_("ext=file extenstion:XPM file:Ascii or Binary (A or B):viewer program. Note: All arguments except the file extension are optional");
-  histhdr = N_("This section contains the data that is in the history");
-
-  if ((tempstr = expand_path (CONFIG_FILE)) == NULL)
-    {
-      printf (_("gFTP Error: Bad config file name %s\n"), CONFIG_FILE);
-      exit (1);
-    }
-
-  if ((conffile = fopen (tempstr, "w+")) == NULL)
-    {
-      printf (_("gFTP Error: Cannot open config file %s: %s\n"), CONFIG_FILE,
-	      g_strerror (errno));
-      exit (1);
-    }
-
-  g_free (tempstr);
-
-  write_comment (conffile, _(hdr));
-  fwrite ("\n", 1, 1, conffile);
-
-  for (pos = 0; config_file_vars[pos].var != NULL; pos++)
-    {
-      if (config_file_vars[pos].type == CONFIG_CHARTEXT ||
-          config_file_vars[pos].type == CONFIG_CHARPASS ||
-          config_file_vars[pos].type == CONFIG_TEXT)
-        {
-          if (*config_file_vars[pos].comment != '\0')
-            write_comment (conffile, _(config_file_vars[pos].comment));
-
-	  fprintf (conffile, "%s=%s\n\n", config_file_vars[pos].key,
-	  	   *(char **) config_file_vars[pos].var == NULL ? "" :
-                   *(char **) config_file_vars[pos].var);
-        }
-      else if (config_file_vars[pos].type == CONFIG_FLOATTEXT)
-        {
-          if (*config_file_vars[pos].comment != '\0')
-            write_comment (conffile, _(config_file_vars[pos].comment));
-
-	  fprintf (conffile, "%s=%.2f\n\n", config_file_vars[pos].key,
-                   *(double *) config_file_vars[pos].var);
-        }
-      else if (config_file_vars[pos].type == CONFIG_INTTEXT ||
-               config_file_vars[pos].type == CONFIG_UINTTEXT ||
-               config_file_vars[pos].type == CONFIG_CHECKBOX ||
-               config_file_vars[pos].type == CONFIG_HIDEINT)
-        {
-          if (*config_file_vars[pos].comment != '\0')
-            write_comment (conffile, _(config_file_vars[pos].comment));
-
-	  fprintf (conffile, "%s=%d\n\n", config_file_vars[pos].key,
-                   *(int *) config_file_vars[pos].var);
-        }
-      else if (config_file_vars[pos].type == CONFIG_COLOR)
-        {
-          if (*config_file_vars[pos].comment != '\0')
-            write_comment (conffile, _(config_file_vars[pos].comment));
-
-          color = config_file_vars[pos].var;
-          fprintf (conffile, "%s=%x:%x:%x\n\n", config_file_vars[pos].key,
-                   color->red, color->green, color->blue);
-        }
-    }
-
-  write_comment (conffile, _(proxyhdr));
-  templist = proxy_hosts;
-  while (templist != NULL)
-    {
-      hosts = templist->data;
-      if (hosts->domain)
-	fprintf (conffile, "dont_use_proxy=%s\n", hosts->domain);
-      else
-	fprintf (conffile, "dont_use_proxy=%d.%d.%d.%d/%d.%d.%d.%d\n",
-		 hosts->ipv4_network_address >> 24 & 0xff,
-		 hosts->ipv4_network_address >> 16 & 0xff,
-		 hosts->ipv4_network_address >> 8 & 0xff,
-		 hosts->ipv4_network_address & 0xff,
-		 hosts->ipv4_netmask >> 24 & 0xff,
-		 hosts->ipv4_netmask >> 16 & 0xff,
-		 hosts->ipv4_netmask >> 8 & 0xff, hosts->ipv4_netmask & 0xff);
-      templist = templist->next;
-    }
-
-  fwrite ("\n", 1, 1, conffile);
-  write_comment (conffile, _(exthdr));
-  templist = registered_exts;
-  while (templist != NULL)
-    {
-      tempext = templist->data;
-      fprintf (conffile, "ext=%s:%s:%c:%s\n", tempext->ext, tempext->filename,
-	       *tempext->ascii_binary == '\0' ? ' ' : *tempext->ascii_binary,
-	       tempext->view_program);
-      templist = templist->next;
-    }
-
-  fwrite ("\n", 1, 1, conffile);
-  write_comment (conffile, _(histhdr));
-  for (templist = localhistory; templist != NULL; templist = templist->next)
-    fprintf (conffile, "localhistory=%s\n", (char *) templist->data);
-
-  for (templist = remotehistory; templist != NULL; templist = templist->next)
-    fprintf (conffile, "remotehistory=%s\n", (char *) templist->data);
-
-  for (templist = host_history; templist != NULL; templist = templist->next)
-    fprintf (conffile, "hosthistory=%s\n", (char *) templist->data);
-
-  for (templist = port_history; templist != NULL; templist = templist->next)
-    fprintf (conffile, "porthistory=%s\n", (char *) templist->data);
-
-  for (templist = user_history; templist != NULL; templist = templist->next)
-    fprintf (conffile, "userhistory=%s\n", (char *) templist->data);
-
-  fclose (conffile);
-}
-
-
-void
-gftp_write_bookmarks_file (void)
-{
-  gftp_bookmarks *tempentry;
-  char *bmhdr, *tempstr;
-  FILE * bmfile;
-
-  bmhdr = N_("Bookmarks file for gFTP. Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>. Warning: Any comments that you add to this file WILL be overwritten");
-
-  if ((tempstr = expand_path (BOOKMARKS_FILE)) == NULL)
-    {
-      printf (_("gFTP Error: Bad bookmarks file name %s\n"), CONFIG_FILE);
-      exit (1);
-    }
-
-  if ((bmfile = fopen (tempstr, "w+")) == NULL)
-    {
-      printf (_("gFTP Error: Cannot open bookmarks file %s: %s\n"),
-	      CONFIG_FILE, g_strerror (errno));
-      exit (1);
-    }
-
-  g_free (tempstr);
-
-  write_comment (bmfile, _(bmhdr));
-  fwrite ("\n", 1, 1, bmfile);
-
-  tempentry = bookmarks->children;
-  while (tempentry != NULL)
-    {
-      if (tempentry->children != NULL)
-	{
-	  tempentry = tempentry->children;
-	  continue;
-	}
-      tempstr = tempentry->path;
-      while (*tempstr == '/')
-	tempstr++;
-      fprintf (bmfile,
-	       "[%s]\nhostname=%s\nport=%d\nprotocol=%s\nremote directory=%s\nlocal directory=%s\nusername=%s\npassword=%s\naccount=%s\n",
-	       tempstr, tempentry->hostname == NULL ? "" : tempentry->hostname,
-	       tempentry->port, tempentry->protocol == NULL
-	       || *tempentry->protocol ==
-	       '\0' ? gftp_protocols[0].name : tempentry->protocol,
-	       tempentry->remote_dir == NULL ? "" : tempentry->remote_dir,
-	       tempentry->local_dir == NULL ? "" : tempentry->local_dir,
-	       tempentry->user == NULL ? "" : tempentry->user,
-	       !tempentry->save_password
-	       || tempentry->pass == NULL ? "" : tempentry->pass,
-	       tempentry->acct == NULL ? "" : tempentry->acct);
-
-      if (tempentry->sftpserv_path)
-        fprintf (bmfile, "sftpserv_path=%s\n", tempentry->sftpserv_path);
-
-      fprintf (bmfile, "\n");
- 
-      if (tempentry->next == NULL)
-	{
-	  tempentry = tempentry->prev;
-	  while (tempentry->next == NULL && tempentry->prev != NULL)
-	    tempentry = tempentry->prev;
-	  tempentry = tempentry->next;
-	}
-      else
-	tempentry = tempentry->next;
-    }
-
-  fclose (bmfile);
-}
-
-
-static void
-write_comment (FILE * fd, const char *comment)
-{
-  const char *pos, *endpos;
-
-  fwrite ("# ", 1, 2, fd);
-  pos = comment;
-  while (strlen (pos) > 76)
-    {
-      for (endpos = pos + 76; *endpos != ' ' && endpos > pos; endpos--);
-      if (endpos == pos)
-	{
-	  for (endpos = pos + 76; *endpos != ' ' && *endpos != '\0';
-	       endpos++);
-	}
-      fwrite (pos, 1, endpos - pos, fd);
-      fwrite ("\n# ", 1, 3, fd);
-      if (*endpos == '\0')
-	{
-	  pos = endpos;
-	  break;
-	}
-      else
-	pos = endpos + 1;
-    }
-  if (strlen (pos) > 1)
-    {
-      fwrite (pos, 1, strlen (pos), fd);
-      fwrite ("\n", 1, 1, fd);
-    }
-}
-
-
 static int
 parse_args (char *str, int numargs, int lineno, char **first, ...)
 {
@@ -1053,10 +319,478 @@
 }
 
 
+static void *
+gftp_config_read_str (char *buf, int line)
+{
+  char *ret;
+
+  ret = g_strdup (buf);
+  return (ret);
+}
+
+
+static void
+gftp_config_write_str (FILE *fd, void *data)
+{
+  fprintf (fd, "%s", (char *) data);
+}
+
+
+static void *
+gftp_config_read_proxy (char *buf, int line)
+{
+  gftp_proxy_hosts * host;
+  unsigned int nums[4];
+  char *pos;
+
+  host = g_malloc0 (sizeof (*host));
+  if ((pos = strchr (buf, '/')) == NULL)
+    host->domain = g_strdup (buf);
+  else
+    {
+      *pos = '\0';
+      sscanf (buf, "%u.%u.%u.%u", &nums[0], &nums[1], &nums[2], &nums[3]);
+      host->ipv4_network_address = 
+                      nums[0] << 24 | nums[1] << 16 | nums[2] << 8 | nums[3];
+
+      if (strchr (pos + 1, '.') == NULL)
+        host->ipv4_netmask = 0xffffffff << (32 - strtol (pos + 1, NULL, 10));
+      else
+        {
+          sscanf (pos + 1, "%u.%u.%u.%u", &nums[0], &nums[1], &nums[2], 
+                  &nums[3]);
+          host->ipv4_netmask =
+		    nums[0] << 24 | nums[1] << 16 | nums[2] << 8 | nums[3];
+        }
+    }
+
+  return (host);
+}
+
+
+static void
+gftp_config_write_proxy (FILE *fd, void *data)
+{
+  gftp_proxy_hosts * host;
+
+  host = data;
+
+  if (host->domain)
+    fprintf (fd, "%s", host->domain);
+  else
+    fprintf (fd, "%d.%d.%d.%d/%d.%d.%d.%d",
+             host->ipv4_network_address >> 24 & 0xff,
+             host->ipv4_network_address >> 16 & 0xff,
+             host->ipv4_network_address >> 8 & 0xff,
+             host->ipv4_network_address & 0xff,
+             host->ipv4_netmask >> 24 & 0xff,
+             host->ipv4_netmask >> 16 & 0xff,
+             host->ipv4_netmask >> 8 & 0xff, 
+             host->ipv4_netmask & 0xff);
+}
+
+
+static void *
+gftp_config_read_ext (char *buf, int line)
+{
+  gftp_file_extensions * tempext;
+  char *tempstr;
+
+  tempext = g_malloc (sizeof (*tempext));
+  parse_args (buf, 4, line, &tempext->ext, &tempext->filename,
+              &tempext->ascii_binary, &tempext->view_program);
+ 
+  if ((tempstr = get_xpm_path (tempext->filename, 1)) != NULL)
+    g_free (tempstr);
+
+  tempext->stlen = strlen (tempext->ext);
+
+  return (tempext);
+}
+
+
+static void
+gftp_config_write_ext (FILE *fd, void *data)
+{
+  gftp_file_extensions * tempext;
+
+  tempext = data;
+  fprintf (fd, "%s:%s:%c:%s", tempext->ext, tempext->filename,
+           *tempext->ascii_binary == '\0' ? ' ' : *tempext->ascii_binary,
+           tempext->view_program);
+}
+
+
+gftp_config_list_vars gftp_config_list[] = {
+  {"dont_use_proxy",	gftp_config_read_proxy,	gftp_config_write_proxy, 
+   NULL, 0,
+   N_("This section specifies which hosts are on the local subnet and won't need to go out the proxy server (if available). Syntax: dont_use_proxy=.domain or dont_use_proxy=network number/netmask")},
+  {"ext",		gftp_config_read_ext,	gftp_config_write_ext,	
+   NULL, 0,
+   N_("ext=file extenstion:XPM file:Ascii or Binary (A or B):viewer program. Note: All arguments except the file extension are optional")},
+  {"localhistory",	gftp_config_read_str,	gftp_config_write_str,	
+   NULL, 0, NULL},
+  {"remotehistory",	gftp_config_read_str,   gftp_config_write_str,	
+    NULL, 0, NULL},
+  {"hosthistory",	gftp_config_read_str,   gftp_config_write_str,	
+    NULL, 0, NULL},
+  {"porthistory",	gftp_config_read_str,   gftp_config_write_str,	
+    NULL, 0, NULL},
+  {"userhistory",	gftp_config_read_str,   gftp_config_write_str,	
+    NULL, 0, NULL},
+  {NULL,		NULL,			NULL,			
+    NULL, 0, NULL}
+};
+
+
+static void
+gftp_setup_global_options (gftp_config_vars * cvars)
+{
+  int i;
+
+  for (i=0; cvars[i].key != NULL; i++)
+    {
+      if (cvars[i].otype == gftp_option_type_subtree)
+        gftp_setup_global_options (cvars[i].value);
+      else if (cvars[i].key != NULL && *cvars[i].key != '\0')
+        g_hash_table_insert (gftp_global_options_htable, 
+                             cvars[i].key, &cvars[i]);
+    }
+}
+
+
+void
+gftp_read_config_file (char **argv, int get_xpms)
+{
+  char *tempstr, *temp1str, *curpos, buf[255];
+  gftp_config_list_vars * tmplistvar;
+  gftp_config_vars * tmpconfigvar;
+  FILE *conffile;
+  int line, i;
+  size_t len;
+
+  gftp_global_options_htable = g_hash_table_new (string_hash_function, 
+                                                 string_hash_compare);
+
+  gftp_register_config_vars (gftp_global_config_vars);
+
+  for (i=0; gftp_protocols[i].register_options != NULL; i++)
+    {
+      if (gftp_protocols[i].register_options != NULL)
+        gftp_protocols[i].register_options ();
+    }
+
+  gftp_config_list_htable = g_hash_table_new (string_hash_function, 
+                                              string_hash_compare);
+
+  for (i=0; gftp_config_list[i].key != NULL; i++)
+    {
+      g_hash_table_insert (gftp_config_list_htable, gftp_config_list[i].key, 
+                           &gftp_config_list[i]);
+    }
+
+  if ((tempstr = expand_path (CONFIG_FILE)) == NULL)
+    {
+      printf (_("gFTP Error: Bad config file name %s\n"), CONFIG_FILE);
+      exit (1);
+    }
+
+  if (access (tempstr, F_OK) == -1)
+    {
+      temp1str = expand_path (BASE_CONF_DIR);
+      if (access (temp1str, F_OK) == -1)
+	{
+	  if (mkdir (temp1str, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
+	    {
+	      printf (_("gFTP Error: Could not make directory %s: %s\n"),
+		      temp1str, g_strerror (errno));
+	      exit (1);
+	    }
+	}
+      g_free (temp1str);
+
+      temp1str = g_strdup_printf ("%s/gftprc", SHARE_DIR);
+      if (access (temp1str, F_OK) == -1)
+	{
+	  printf (_("gFTP Error: Cannot find master config file %s\n"),
+		  temp1str);
+	  printf (_("Did you do a make install?\n"));
+	  exit (1);
+	}
+      copyfile (temp1str, tempstr);
+      g_free (temp1str);
+    }
+
+  if ((conffile = fopen (tempstr, "r")) == NULL)
+    {
+      printf (_("gFTP Error: Cannot open config file %s: %s\n"), CONFIG_FILE,
+	      g_strerror (errno));
+      exit (1);
+    }
+  g_free (tempstr);
+ 
+  line = 0;
+  while (fgets (buf, sizeof (buf), conffile))
+    {
+      len = strlen (buf);
+      if (len > 0 && buf[len - 1] == '\n')
+	buf[--len] = '\0';
+      if (len > 0 && buf[len - 1] == '\r')
+	buf[--len] = '\0';
+      line++;
+
+      if (*buf == '#' || *buf == '\0')
+        continue;
+
+      if ((curpos = strchr (buf, '=')) == NULL)
+        continue;
+
+      *curpos = '\0';
+
+      if ((tmplistvar = g_hash_table_lookup (gftp_config_list_htable, 
+                                             buf)) != NULL)
+        {
+          tmplistvar->list = g_list_append (tmplistvar->list, 
+                                            tmplistvar->read_func (curpos + 1,
+                                                                   line));
+          tmplistvar->num_items++;
+        }
+      else if ((tmpconfigvar = g_hash_table_lookup (gftp_global_options_htable,
+                                                    buf)) != NULL &&
+               gftp_option_types[tmpconfigvar->otype].read_function != NULL)
+        {
+          if (gftp_option_types[tmpconfigvar->otype].read_function (curpos + 1, 
+                                tmpconfigvar, line) != 0)
+            {
+              printf (_("Terminating due to parse errors at line %d in the config file\n"), line);
+              exit (1);
+            }
+        }
+      else
+	{
+	  printf (_("gFTP Warning: Skipping line %d in config file: %s\n"),
+                  line, buf);
+	}
+    }
+
+/* FIXME
+  gftp_lookup_global_option ("default_protocol", &tempstr);
+  if (tempstr == NULL || *tempstr == '\0')
+    {
+      tempstr = "FTP";
+      gftp_set_global_option ("default_protocol", tempstr);
+    }
+
+  for (i = 0; gftp_protocols[i].name; i++)
+    {
+      if (strcmp (gftp_protocols[i].name, tempstr) == 0)
+        break;
+    }
+
+  if (gftp_protocols[i].name == NULL)
+    {
+      printf (_("gFTP Error: Default protocol %s is not a valid protocol\n"), tempstr);
+      exit (1);
+    }
+*/
+  if ((tempstr = expand_path (LOG_FILE)) == NULL)
+    {
+      printf (_("gFTP Error: Bad log file name %s\n"), LOG_FILE);
+      exit (1);
+    }
+
+  if ((gftp_logfd = fopen (tempstr, "w")) == NULL)
+    {
+      printf (_("gFTP Warning: Cannot open %s for writing: %s\n"),
+              tempstr, g_strerror (errno));
+    }
+  g_free (tempstr);
+
+  gftp_bookmarks = g_malloc0 (sizeof (*gftp_bookmarks));
+  gftp_bookmarks->isfolder = 1;
+  gftp_bookmarks->path = g_malloc0 (1);
+  gftp_bookmarks_htable = g_hash_table_new (string_hash_function, string_hash_compare);
+
+  gftp_read_bookmarks ();
+}
+
+
+static void
+write_comment (FILE * fd, const char *comment)
+{
+  const char *pos, *endpos;
+
+  fwrite ("# ", 1, 2, fd);
+  pos = comment;
+  while (strlen (pos) > 76)
+    {
+      for (endpos = pos + 76; *endpos != ' ' && endpos > pos; endpos--);
+      if (endpos == pos)
+	{
+	  for (endpos = pos + 76; *endpos != ' ' && *endpos != '\0';
+	       endpos++);
+	}
+      fwrite (pos, 1, endpos - pos, fd);
+      fwrite ("\n# ", 1, 3, fd);
+      if (*endpos == '\0')
+	{
+	  pos = endpos;
+	  break;
+	}
+      else
+	pos = endpos + 1;
+    }
+  if (strlen (pos) > 1)
+    {
+      fwrite (pos, 1, strlen (pos), fd);
+      fwrite ("\n", 1, 1, fd);
+    }
+}
+
+
+void
+gftp_write_bookmarks_file (void)
+{
+  gftp_bookmarks_var * tempentry;
+  char *bmhdr, *tempstr;
+  FILE * bmfile;
+
+  bmhdr = N_("Bookmarks file for gFTP. Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>. Warning: Any comments that you add to this file WILL be overwritten");
+
+  if ((tempstr = expand_path (BOOKMARKS_FILE)) == NULL)
+    {
+      printf (_("gFTP Error: Bad bookmarks file name %s\n"), CONFIG_FILE);
+      exit (1);
+    }
+
+  if ((bmfile = fopen (tempstr, "w+")) == NULL)
+    {
+      printf (_("gFTP Error: Cannot open bookmarks file %s: %s\n"),
+	      CONFIG_FILE, g_strerror (errno));
+      exit (1);
+    }
+
+  g_free (tempstr);
+
+  write_comment (bmfile, _(bmhdr));
+  fwrite ("\n", 1, 1, bmfile);
+
+  tempentry = gftp_bookmarks->children;
+  while (tempentry != NULL)
+    {
+      if (tempentry->children != NULL)
+	{
+	  tempentry = tempentry->children;
+	  continue;
+	}
+      tempstr = tempentry->path;
+      while (*tempstr == '/')
+	tempstr++;
+      fprintf (bmfile,
+	       "[%s]\nhostname=%s\nport=%d\nprotocol=%s\nremote directory=%s\nlocal directory=%s\nusername=%s\npassword=%s\naccount=%s\n",
+	       tempstr, tempentry->hostname == NULL ? "" : tempentry->hostname,
+	       tempentry->port, tempentry->protocol == NULL
+	       || *tempentry->protocol ==
+	       '\0' ? gftp_protocols[0].name : tempentry->protocol,
+	       tempentry->remote_dir == NULL ? "" : tempentry->remote_dir,
+	       tempentry->local_dir == NULL ? "" : tempentry->local_dir,
+	       tempentry->user == NULL ? "" : tempentry->user,
+	       !tempentry->save_password
+	       || tempentry->pass == NULL ? "" : tempentry->pass,
+	       tempentry->acct == NULL ? "" : tempentry->acct);
+
+      if (tempentry->sftpserv_path)
+        fprintf (bmfile, "sftpserv_path=%s\n", tempentry->sftpserv_path);
+
+      fprintf (bmfile, "\n");
+ 
+      if (tempentry->next == NULL)
+	{
+	  tempentry = tempentry->prev;
+	  while (tempentry->next == NULL && tempentry->prev != NULL)
+	    tempentry = tempentry->prev;
+	  tempentry = tempentry->next;
+	}
+      else
+	tempentry = tempentry->next;
+    }
+
+  fclose (bmfile);
+}
+
+
+void
+gftp_write_config_file (void)
+{
+  gftp_config_vars * cv;
+  GList *templist;
+  FILE *conffile;
+  char *tempstr;
+  int i;
+
+  if ((tempstr = expand_path (CONFIG_FILE)) == NULL)
+    {
+      printf (_("gFTP Error: Bad config file name %s\n"), CONFIG_FILE);
+      exit (1);
+    }
+
+  if ((conffile = fopen (tempstr, "w+")) == NULL)
+    {
+      printf (_("gFTP Error: Cannot open config file %s: %s\n"), CONFIG_FILE,
+	      g_strerror (errno));
+      exit (1);
+    }
+
+  g_free (tempstr);
+
+  write_comment (conffile, _("Config file for gFTP. Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>. Warning: Any comments that you add to this file WILL be overwritten. If a entry has a (*) in it's comment, you can't change it inside gFTP"));
+
+  for (templist = gftp_options_list;
+       templist != NULL;
+       templist = templist->next)
+    {
+      cv = templist->data;
+
+      for (i=0; cv[i].key != NULL; i++)
+        {
+          if (gftp_option_types[cv[i].otype].write_function == NULL ||
+              *cv[i].key == '\0')
+            continue;
+
+          fprintf (conffile, "\n");
+          if (cv[i].comment != NULL)
+            write_comment (conffile, _(cv[i].comment));
+
+          fprintf (conffile, "%s=", cv[i].key);
+          gftp_option_types[cv[i].otype].write_function (&cv[i], conffile, 1);
+          fprintf (conffile, "\n");
+        }
+    }
+    
+  for (i=0; gftp_config_list[i].list != NULL; i++)
+    {
+      fprintf (conffile, "\n");
+      if (gftp_config_list[i].header != NULL)
+        write_comment (conffile, _(gftp_config_list[i].header));
+
+      for (templist = gftp_options_list;
+           templist != NULL;
+           templist = templist->next)
+        {
+          fprintf (conffile, "%s=", gftp_config_list[i].key);
+          gftp_config_list[i].write_func (conffile, templist->data);
+          fprintf (conffile, "\n");
+        }
+    }
+
+  fclose (conffile);
+}
+
+
 GHashTable *
-build_bookmarks_hash_table (gftp_bookmarks * entry)
+build_bookmarks_hash_table (gftp_bookmarks_var * entry)
 {
-  gftp_bookmarks * tempentry;
+  gftp_bookmarks_var * tempentry;
   GHashTable * htable;
 
   htable = g_hash_table_new (string_hash_function, string_hash_compare);
@@ -1078,9 +812,9 @@
 
 
 void
-print_bookmarks (gftp_bookmarks * bookmarks)
+print_bookmarks (gftp_bookmarks_var * bookmarks)
 {
-  gftp_bookmarks * tempentry;
+  gftp_bookmarks_var * tempentry;
 
   tempentry = bookmarks->children;
   while (tempentry != NULL)
@@ -1103,3 +837,283 @@
     }
 }
 
+
+static int
+gftp_config_file_read_text (char *str, gftp_config_vars * cv, int line)
+{
+  if (str != NULL)
+    {
+      cv->value = g_strdup (str);
+      return (0);
+    }
+  else
+    return (-1);
+}
+
+
+static int
+gftp_config_file_write_text (gftp_config_vars * cv, FILE * fd, int to_config_file)
+{
+  char *outstr;
+
+  if (cv->value != NULL)
+    {
+      outstr = cv->value;
+      if (*outstr != '\0')
+        fprintf (fd, "%s", outstr);
+      return (0);
+    }
+  else
+    return (-1);
+}
+
+
+static int
+gftp_config_file_write_hidetext (gftp_config_vars * cv, FILE * fd, int to_config_file)
+{
+  char *outstr;
+
+  if (cv->value != NULL)
+    {
+      outstr = cv->value;
+      if (*outstr != '\0')
+        {
+          if (to_config_file)
+            fprintf (fd, "%s", outstr);
+          else
+            fprintf (fd, "*****");
+        }
+      return (0);
+    }
+  else
+    return (-1);
+}
+
+
+static int
+gftp_config_file_copy_text (void *dest, void *src)
+{
+  *(char **) dest = src;
+  return (0);
+}
+
+
+static int
+gftp_config_file_read_int (char *str, gftp_config_vars * cv, int line)
+{
+  cv->value = GINT_TO_POINTER(strtol (str, NULL, 10));
+  return (0);
+}
+
+
+static int
+gftp_config_file_write_int (gftp_config_vars * cv, FILE * fd, int to_config_file)
+{
+  fprintf (fd, "%d", GPOINTER_TO_INT(cv->value));
+  return (0);
+}
+
+
+static int
+gftp_config_file_copy_int (void *dest, void *src)
+{
+  *(int *) dest = GPOINTER_TO_INT(src);
+  return (0);
+}
+
+
+static int
+gftp_config_file_read_checkbox (char *str, gftp_config_vars * cv, int line)
+{
+  cv->value = GINT_TO_POINTER(strtol (str, NULL, 10) ? 1 : 0);
+  return (0);
+}
+
+
+static int
+gftp_config_file_read_float (char *str, gftp_config_vars * cv, int line)
+{
+  *(float *) cv->value = strtof (str, NULL);
+  return (0);
+}
+
+
+static int
+gftp_config_file_write_float (gftp_config_vars * cv, FILE * fd, int to_config_file)
+{
+  fprintf (fd, "%.2f", 0.0); /* FIXME */
+  return (0);
+}
+
+
+static int
+gftp_config_file_copy_float (void *dest, void *src)
+{
+  *(float *) dest = 0.0; /* FIXME */
+  return (0);
+}
+
+
+static int
+gftp_config_file_read_color (char *str, gftp_config_vars * cv, int line)
+{
+  char *red, *green, *blue;
+  gftp_color * color;
+
+  parse_args (str, 3, line, &red, &green, &blue);
+
+  color = g_malloc (sizeof (*color));
+  color->red = strtol (red, NULL, 16);
+  color->green = strtol (green, NULL, 16);
+  color->blue = strtol (blue, NULL, 16);
+  g_free (red);
+  g_free (green);
+  g_free (blue);
+
+  cv->value = color;
+
+  return (0);
+}
+
+
+static int
+gftp_config_file_write_color (gftp_config_vars * cv, FILE * fd, int to_config_file)
+{
+  gftp_color * color;
+
+  color = cv->value;
+  fprintf (fd, "%x:%x:%x", color->red, color->green, color->blue);
+  return (0);
+}
+
+
+static int
+gftp_config_file_copy_color (void *dest, void *src)
+{
+  *(gftp_color **) dest = src;
+  return (0);
+}
+
+
+static int
+gftp_config_file_read_intcombo (char *str, gftp_config_vars * cv, int line)
+{
+  char **clist;
+  int i;
+
+  cv->value = 0;
+  if (cv->listdata != NULL)
+    {
+      clist = cv->listdata;
+      for (i=0; clist[i] != NULL; i++)
+        {
+          if (strcasecmp (_(clist[i]), str) == 0)
+            {
+              cv->value = GINT_TO_POINTER(i);
+              break;
+            }
+        }
+    }
+
+  return (0);
+}
+
+
+static int
+gftp_config_file_write_intcombo (gftp_config_vars * cv, FILE * fd, int to_config_file)
+{
+  char **clist;
+
+  clist = cv->listdata;
+  if (clist != NULL)
+    fprintf (fd, "%s", _(clist[GPOINTER_TO_INT(cv->value)]));
+  else
+    fprintf (fd, _("<unknown>"));
+
+  return (0);
+}
+
+
+/* *Note, the index numbers of this array must match up to the numbers in
+   gftp_option_type_enum in gftp.h */
+gftp_option_type_var gftp_option_types[] = {
+  {gftp_config_file_read_text, gftp_config_file_write_text,
+   NULL, gftp_config_file_copy_text, NULL},
+  {NULL, NULL, NULL, NULL, NULL}, /* FIXME _ textarray */
+  {gftp_config_file_read_int, gftp_config_file_write_int,
+   NULL, gftp_config_file_copy_int, NULL},
+  {gftp_config_file_read_float, gftp_config_file_write_float,
+   NULL, gftp_config_file_copy_float, NULL},
+  {gftp_config_file_read_checkbox, gftp_config_file_write_int,
+   NULL, gftp_config_file_copy_int, NULL},
+  {gftp_config_file_read_color, gftp_config_file_write_color,
+   NULL, gftp_config_file_copy_color, NULL},
+  {NULL, NULL, NULL, NULL, NULL},
+  {NULL, NULL, NULL, NULL, NULL},
+  {gftp_config_file_read_text, gftp_config_file_write_hidetext,
+   NULL, gftp_config_file_copy_text, NULL},
+  {NULL, NULL, NULL, NULL, NULL},
+  {gftp_config_file_read_text, gftp_config_file_write_text,
+   NULL, gftp_config_file_copy_text, NULL},
+  {NULL, NULL, NULL, NULL, NULL},
+  {gftp_config_file_read_intcombo, gftp_config_file_write_intcombo, 
+   NULL, gftp_config_file_copy_int, NULL},
+  {NULL, NULL, NULL, NULL, NULL},
+  {NULL, NULL, NULL, NULL, NULL}
+};
+
+
+void
+gftp_lookup_global_option (char * key, void *value)
+{
+  gftp_config_list_vars * tmplistvar;
+  gftp_config_vars * tmpconfigvar;
+
+  if (gftp_global_options_htable != NULL &&
+      (tmpconfigvar = g_hash_table_lookup (gftp_global_options_htable,
+                                           key)) != NULL)
+    {
+      if (gftp_option_types[tmpconfigvar->otype].config_copy_function == NULL)
+        return;
+
+      gftp_option_types[tmpconfigvar->otype].config_copy_function (value, tmpconfigvar->value);
+    }
+  else if ((tmplistvar = g_hash_table_lookup (gftp_config_list_htable, 
+                                              key)) != NULL)
+    {
+      *(gftp_config_list_vars **) value = tmplistvar;
+    }
+  else
+    {
+      fprintf (stderr, _("FATAL gFTP Error: Config option '%s' not found in global hash table\n"), key);
+      exit (1);
+    }
+}
+
+
+void
+gftp_lookup_request_option (gftp_request * request, char * key, void *value)
+{
+  gftp_lookup_global_option (key, value);
+}
+
+
+void
+gftp_set_global_option (char * key, void *value)
+{
+}
+
+
+void
+gftp_set_request_option (gftp_request * request, char * key, void *value)
+{
+}
+
+
+void
+gftp_register_config_vars (gftp_config_vars * config_vars)
+{
+  gftp_options_list = g_list_append (gftp_options_list, config_vars);
+  gftp_setup_global_options (config_vars);
+}
+
--- a/lib/gftp.h	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/gftp.h	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  gftp.h - include file for the whole ftp program                          */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -97,13 +97,13 @@
 #endif
 
 /* Server types (used by FTP protocol from SYST command) */
-#define GFTP_TYPE_UNIX		1
-#define GFTP_TYPE_EPLF		2
-#define GFTP_TYPE_CRAY		3	
-#define GFTP_TYPE_NOVELL	4	
-#define GFTP_TYPE_DOS		5	
-#define GFTP_TYPE_VMS		6	
-#define GFTP_TYPE_OTHER 	7
+#define GFTP_DIRTYPE_UNIX	1
+#define GFTP_DIRTYPE_EPLF	2
+#define GFTP_DIRTYPE_CRAY	3	
+#define GFTP_DIRTYPE_NOVELL	4	
+#define GFTP_DIRTYPE_DOS	5	
+#define GFTP_DIRTYPE_VMS	6	
+#define GFTP_DIRTYPE_OTHER 	7
 
 /* Error types */
 #define GFTP_ERETRYABLE		-1
@@ -160,13 +160,16 @@
        *attribs,		/* Attribs (-rwxr-x-rx) */
        *destfile;		/* Full pathname to the destination for the 
                                    file transfer */
+
+  int fd;			/* Already open fd for this file */
+  /* FIXME - add fd_open function */
+
   time_t datetime;		/* File date and time */
   off_t size,			/* Size of the file */
         startsize;		/* Size to start the transfer at */
   unsigned int isdir : 1,	/* File type */
                isexe : 1,
                islink : 1,
-               ascii : 1, 	/* Transfer in ASCII mode */
                selected : 1,	/* Is this file selected? */
                was_sel : 1,	/* Was this file selected before  */
                shown : 1,	/* Is this file shown? */
@@ -176,19 +179,19 @@
                transfer_done : 1, /* Is current file transfer done? */
                is_fd : 1;	/* Is this a file descriptor? */
   char transfer_action;		/* See the GFTP_TRANS_ACTION_* vars above */
-  void *node;			/* FIXME Pointer to the node for the gui */
-  int fd;
+  void *user_data;
 };
 
 
 typedef struct gftp_proxy_hosts_tag 
 {
-  gint32 ipv4_network_address,
+  /* FIXME - add IPV4 stuff here */
+
+  gint32 ipv4_network_address, 
          ipv4_netmask;
   char *domain;
 } gftp_proxy_hosts;
 
-
 typedef struct gftp_request_tag gftp_request;
 
 struct gftp_request_tag 
@@ -200,35 +203,30 @@
        *password,		/* Password for host */
        *account,		/* Account for host (FTP only) */
        *directory,		/* Current working directory */
-       *proxy_config,		/* Proxy configuration */
-       *proxy_hostname,		/* Proxy hostname */
-       *proxy_username,		/* Proxy username */
-       *proxy_password,		/* Proxy password */
-       *proxy_account,		/* Proxy account (FTP only) */
        *url_prefix,		/* URL Prefix (ex: ftp) */
-       *protocol_name,		/* Protocol description */
        *last_ftp_response,	/* Last response from server */
        *last_dir_entry;		/* Last dir entry from server */
   size_t last_dir_entry_len;	/* Length of last_dir_entry */
 
-  unsigned int port,		/* Port of remote site */
-               proxy_port;	/* Port of the proxy server */
+  unsigned int port;		/* Port of remote site */
 
   int sockfd,			/* Control connection (read) */
       datafd,			/* Data connection */
       cachefd;			/* For the directory cache */
   int wakeup_main_thread[2];	/* FD that gets written to by the threads
                                    to wakeup the parent */
-        
+
+  /* One of these are used to lookup the IP address of the host we are
+     connecting to */
 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-  struct addrinfo *hostp;	/* Remote host we are connected to */
+  struct addrinfo *hostp;
 #else
-  struct hostent host, *hostp;  /* Remote host we are connected to */
+  struct hostent host, *hostp;
 #endif
 
-  int data_type,		/* ASCII or BINARY (FTP only) */
-      server_type;		/* The type of server we are connected to */
-  unsigned int use_proxy : 1,           /* Go out of proxy server */
+  int server_type;		/* The type of server we are connected to.
+                                   See GFTP_DIRTYPE_* above */
+  unsigned int use_proxy : 1,
                always_connected : 1,
                need_hostport : 1,
                need_userpass : 1,
@@ -278,8 +276,6 @@
   int (*get_next_file)			( gftp_request * request, 
 					  gftp_file *fle, 
 					  int fd );
-  int (*set_data_type)			( gftp_request * request, 
-					  int data_type );
   off_t (*get_file_size) 		( gftp_request * request, 
 					  const char *filename );
   int (*chdir)				( gftp_request * request, 
@@ -307,14 +303,7 @@
   void (*swap_socks)			( gftp_request * dest,
 					  gftp_request * source );
 
-  /* Options */
-  gftp_transfer_type transfer_type;	/* Passive or non-passive (FTP only) */
-  int network_timeout,
-      retries,
-      sleep_time,
-      passive_transfer;
-  float maxkbs;
-  char *sftpserv_path;
+  GHashTable * local_options;
 };
 
 
@@ -360,8 +349,9 @@
   void * fromwdata,
        * towdata;
 
-  void *statmutex,
-       *structmutex;
+  GStaticMutex statmutex,
+               structmutex;
+
   void *node;
   void *clist;
 };
@@ -378,13 +368,15 @@
 {
   char *name;					/* Description of protocol */
   void (*init) (gftp_request * request);	/* Init function */
+  void (*register_options) (void);		/* Protocol options */
   char *url_prefix;				/* URL Prefix */
-  int shown;					/* Whether this protocol is shown or not to the user
-                                                   in the protocol dropdown box */
+  int shown;					/* Whether this protocol is 
+                                                   shown or not to the user in 
+                                                   the protocol dropdown box */
 } supported_gftp_protocols;
 
 
-typedef struct gftp_bookmarks_tag gftp_bookmarks;
+typedef struct gftp_bookmarks_tag gftp_bookmarks_var;
 
 struct gftp_bookmarks_tag 
 {
@@ -401,9 +393,9 @@
                isfolder : 1,   /* If this is set, then the children field can
                                   be non-NULL */
                save_password : 1; /* Save this password */
-  gftp_bookmarks *children, 	/* The children of this node. */
-                 *prev, 	/* The parent of this node */
-                 *next; 	/* The next sibling of this node */
+  gftp_bookmarks_var *children, /* The children of this node. */
+                     *prev, 	/* The parent of this node */
+                     *next; 	/* The next sibling of this node */
   gpointer cnode; 
 
   /* Site options */
@@ -429,40 +421,79 @@
 } gftp_color;
 
 
-typedef struct gftp_config_vars_tag
+/* Note, these numbers must match up to the index number in config_file.c
+   in the declaration of gftp_option_types */
+typedef enum 
 {
-  char *key,			/* variable name */
-       *description;		/* How this field will show up in the dialog */
-  gpointer var;			/* Pointer to our variable */
-  int type;			/* See defines below */
-  char *comment;                /* Comment to write out to the config file */
-  gpointer widget;
-  int ports_shown;		/* What ports of gFTP is this option shown in */
-} gftp_config_vars;
+  gftp_option_type_text		= 0,
+  gftp_option_type_textarray	= 1,
+  gftp_option_type_int		= 2,
+  gftp_option_type_float	= 3,
+  gftp_option_type_checkbox	= 4,
+  gftp_option_type_color	= 5,
+  gftp_option_type_notebook	= 6,
+  gftp_option_type_newtable	= 7,
+  gftp_option_type_hidetext	= 8,
+  gftp_option_type_label	= 9,
+  gftp_option_type_textbox	= 10,
+  gftp_option_type_subtree	= 11,
+  gftp_option_type_intcombo	= 12,
+  gftp_option_type_charcombo	= 13,
+  gftp_option_type_table	= 14
+} gftp_option_type_enum;
 
-#define CONFIG_INTTEXT                  1
-#define CONFIG_FLOATTEXT                2
-#define CONFIG_CHECKBOX                 3       
-#define CONFIG_LABEL                    4
-#define CONFIG_NOTEBOOK                 5
-#define CONFIG_HIDEINT                  6
-#define CONFIG_TABLE			7
-#define CONFIG_CHARTEXT                 8
-#define CONFIG_COMBO			9
-#define CONFIG_TEXT			10
-#define CONFIG_COLOR			11
-#define CONFIG_UINTTEXT                 12
-#define CONFIG_CHARPASS			13
 
 #define GFTP_PORT_GTK			(1 << 1)
 #define GFTP_PORT_TEXT			(1 << 2)
 #define GFTP_PORT_ALL			(GFTP_PORT_GTK | GFTP_PORT_TEXT)
 
-typedef struct gftp_proxy_type_tag
+
+typedef struct gftp_config_list_vars_tag
+{
+  char *key;
+  void * (*read_func) (char *buf, int line);
+  void (*write_func) (FILE *fd, void *data);
+  GList * list;
+  unsigned int num_items;
+  char *header;
+} gftp_config_list_vars;
+
+
+#define GFTP_CVARS_FLAGS_DYNMEM		(1 << 1)
+
+
+typedef struct gftp_config_vars_tag
+{
+  char *key,			/* variable name */
+       *description;		/* How this field will show up in the dialog */
+  int otype;			/* Type of option this is */
+  void *value;
+  void *listdata;		/* For options that have several different 
+				   options, this is a list of all the options.
+				   Each option_type that uses this will use this
+				   field differently */
+  int flags;			/* See GFTP_CVARS_FLAGS_* above */
+  char *comment;                /* Comment to write out to the config file */
+  int ports_shown;		/* What ports of gFTP is this option shown in */
+  void *user_data;		/* Data that the GUI can store here (Widget in gtk+) */
+} gftp_config_vars;
+
+
+typedef struct gftp_option_type_tag
+{
+  int (*read_function) (char *str, gftp_config_vars * cv, int line);
+  int (*write_function) (gftp_config_vars * cv, FILE * fd, int to_config_file);
+  int (*ui_print_function) (char *label, void *ptr, void *user_data);
+  int (*config_copy_function) (void *dest, void *src);
+  void *user_data;
+} gftp_option_type_var;
+
+
+typedef struct gftp_proxy_type_var_tag
 {
   char *key,
        *description;
-} gftp_proxy_type;
+} gftp_proxy_type_var;
 
 #define GFTP_CUSTOM_PROXY_NUM        8
 
@@ -474,40 +505,21 @@
          cur_bufsize;
 } gftp_getline_buffer;
 
-/* Global config options */
+/* Global config options. These are defined in options.h */
+extern GList * gftp_file_transfers, * gftp_file_transfer_logs,
+             * gftp_options_list;
+extern GHashTable * gftp_global_options_htable, * gftp_bookmarks_htable, 
+                  * gftp_config_list_htable;
+extern gftp_config_vars gftp_global_config_vars[];
 extern supported_gftp_protocols gftp_protocols[];
-extern char version[], *emailaddr, *edit_program, *view_program, 
-            *firewall_host, *firewall_username, *firewall_password, 
-            *firewall_account, *proxy_config, *http_proxy_host, 
-            *http_proxy_username, *http_proxy_password, 
-            *startup_directory, *ssh_prog_name, *ssh_extra_params, 
-            **ssh_extra_params_list, *default_protocol, *ssh2_sftp_path;
-extern int num_ssh_extra_params;
-extern FILE * logfd;
-extern double maxkbs;
-extern GList * proxy_hosts, * registered_exts, * viewedit_processes, 
-             * file_transfers, * file_transfer_logs;
-extern gftp_bookmarks * bookmarks;
-extern int do_one_transfer_at_a_time, start_file_transfers, 
-           transfer_in_progress, passive_transfer, sort_dirs_first, 
-           show_hidden_files, refresh_files, listbox_local_width, 
-           listbox_remote_width, listbox_file_height, transfer_height, 
-           log_height, retries, sleep_time, network_timeout, use_http11, 
-           listbox_dblclick_action, file_trans_column, local_columns[6], 
-           remote_columns[6], resolve_symlinks, firewall_port, http_proxy_port,
-           overwrite_by_default, append_file_transfers, 
-           ssh_need_userpass, ssh_use_askpass, sshv2_use_sftp_subsys, 
-           local_sortcol, local_sortasds, remote_sortcol, remote_sortasds;
-extern guint max_log_window_size;
-extern GHashTable * bookmarks_htable, * config_htable;
-extern GList * localhistory, * remotehistory, * host_history, * port_history, 
-             * user_history;
-extern unsigned int host_len, port_len, user_len, localhistlen, remotehistlen;
-extern volatile sig_atomic_t viewedit_process_done;
-extern gftp_config_vars config_file_vars[];
-extern gftp_proxy_type proxy_type[];
-extern gftp_color send_color, recv_color, error_color, misc_color;
-extern struct lconv *my_localeinfo;
+extern gftp_proxy_type_var gftp_proxy_type[];
+extern gftp_bookmarks_var * gftp_bookmarks;
+extern char gftp_version[];
+extern FILE * gftp_logfd;
+
+/* This is defined in config_file.c */
+
+extern gftp_option_type_var gftp_option_types[];
 
 /* cache.c */
 int gftp_new_cache_entry 		( gftp_request * request );
@@ -520,20 +532,34 @@
 					  int ignore_directory );
 
 /* config_file.c */
+void gftp_add_bookmark 			( gftp_bookmarks_var * newentry );
+
 void gftp_read_config_file 		( char **argv,
 					  int get_xpms );
 
-void gftp_read_bookmarks 		( void );
-
-void add_to_bookmark                    ( gftp_bookmarks *newentry );
+void gftp_write_bookmarks_file 		( void );
 
 void gftp_write_config_file 		( void );
 
-void gftp_write_bookmarks_file 		( void );
+GHashTable * build_bookmarks_hash_table	( gftp_bookmarks_var * entry );
+
+void print_bookmarks 			( gftp_bookmarks_var * bookmarks );
+
+void gftp_lookup_global_option 		( char * key, 
+					  void *value );
 
-GHashTable * build_bookmarks_hash_table	( gftp_bookmarks * entry );
+void gftp_lookup_request_option 	( gftp_request * request, 
+					  char * key, 
+					  void *value );
 
-void print_bookmarks 			( gftp_bookmarks * bookmarks );
+void gftp_set_global_option 		( char * key, 
+					  void *value );
+
+void gftp_set_request_option 		( gftp_request * request, 
+					  char * key, 
+					  void *value );
+
+void gftp_register_config_vars 		( gftp_config_vars *config_vars );
 
 /* misc.c */
 char *insert_commas 			( off_t number, 
@@ -588,55 +614,17 @@
 
 int tty_raw 				( int fd );
 
-char **make_ssh_exec_args 		( gftp_request * request, 
-					  char *execname,
-					  int use_sftp_subsys,
-					  char *portstring );
-
-char * ssh_start_login_sequence 	( gftp_request * request, 
-					  int fd );
-
-#ifdef G_HAVE_GINT64
-gint64 hton64				( gint64 val );
-#endif
-
 GList * gftp_sort_filelist 		( GList * filelist, 
 					  int column, 
 					  int asds );
 
 /* protocols.c */
-#define GFTP_GET_HOSTNAME(request)		(request->hostname)
-#define GFTP_GET_USERNAME(request)		(request->username)
-#define GFTP_GET_PASSWORD(request)		(request->password)
-#define GFTP_GET_ACCOUNT(request)		(request->account)
-#define GFTP_GET_DIRECTORY(request)		(request->directory)
-#define GFTP_GET_PORT(request)			(request->port)
-#define GFTP_GET_PROXY_CONFIG(request)		(request->proxy_config)
-#define GFTP_GET_PROXY_HOSTNAME(request)	(request->proxy_hostname)
-#define GFTP_GET_PROXY_USERNAME(request)	(request->proxy_username)
-#define GFTP_GET_PROXY_PASSWORD(request)	(request->proxy_password)
-#define GFTP_GET_PROXY_ACCOUNT(request)		(request->proxy_account)
-#define GFTP_GET_PROXY_PORT(request)		(request->proxy_port)
-#define GFTP_GET_URL_PREFIX(request)		(request->url_prefix)
-#define GFTP_GET_PROTOCOL_NAME(request)		(request->protocol_name)
-#define GFTP_GET_LAST_RESPONSE(request)		(request->last_ftp_response)
-#define GFTP_GET_LAST_DIRENT(request)		(request->last_dir_entry)
-#define GFTP_GET_LAST_DIRENT_LEN(request)	(request->last_dir_entry_len)
-#define GFTP_GET_CONTROL_FD(request)		(request->sockfd)
-#define GFTP_GET_DATA_FD(request)		(request->datafd)
-#define GFTP_GET_DATA_TYPE(request)		(request->data_type)
-#define GFTP_GET_TRANSFER_TYPE(request)		(request->transfer_type)
-#define GFTP_SET_TRANSFER_TYPE(request,val) 	(request->transfer_type = (val))
-#define GFTP_GET_LOGGING(request)		(request->logging)
-#define GFTP_SET_LOGGING(request, val)		(request->logging = (val))
-#define GFTP_UNSAFE_SYMLINKS(request)		(request->unsafe_symlinks)
 #define GFTP_FTP_NUM				0
 #define GFTP_HTTP_NUM				1
 #define GFTP_LOCAL_NUM				2
 #define GFTP_SSHV2_NUM				3
 #define GFTP_BOOKMARK_NUM			4
-#define GFTP_TYPE_BINARY			1
-#define GFTP_TYPE_ASCII				2   
+
 #define GFTP_IS_CONNECTED(request)		((request) != NULL && \
                                                  ((request)->sockfd > 0 || \
                                                   (request)->cached || \
@@ -645,18 +633,28 @@
 
 void rfc959_init 			( gftp_request * request );
 
+void rfc959_register_module		( void );
+
 int rfc959_get_next_file 		( gftp_request * request, 
 					  gftp_file *fle, 
 					  int fd );
 
 void rfc2068_init 			( gftp_request * request );
 
+void rfc2068_register_module		( void );
+
 void local_init 			( gftp_request * request );
 
+void local_register_module		( void );
+
 void sshv2_init 			( gftp_request * request );
 
+void sshv2_register_module		( void );
+
 void bookmark_init 			( gftp_request * request );
 
+void bookmark_register_module		( void );
+
 gftp_request *gftp_request_new 		( void );
 
 void gftp_request_destroy 		( gftp_request * request,
@@ -712,11 +710,6 @@
 
 int gftp_abort_transfer 		( gftp_request * request );
 
-int gftp_read_response 			( gftp_request * request );
-
-int gftp_set_data_type 			( gftp_request * request, 
-					  int data_type );
-
 void gftp_set_hostname 			( gftp_request * request, 
 					  const char *hostname );
 
@@ -735,21 +728,6 @@
 void gftp_set_port 			( gftp_request * request, 
 					  unsigned int port );
 
-void gftp_set_proxy_hostname 		( gftp_request * request, 
-					  const char *hostname );
-
-void gftp_set_proxy_username 		( gftp_request * request, 
-					  const char *username );
-
-void gftp_set_proxy_password 		( gftp_request * request, 
-					  const char *password );
-
-void gftp_set_proxy_account 		( gftp_request * request, 
-					  const char *account );
-
-void gftp_set_proxy_port 		( gftp_request * request, 
-					  unsigned int port );
-
 int gftp_remove_directory 		( gftp_request * request, 
 					  const char *directory );
 
@@ -774,19 +752,9 @@
 char gftp_site_cmd 			( gftp_request * request, 
 					  const char *command );
 
-void gftp_set_proxy_config 		( gftp_request * request, 
-					  const char *proxy_config );
-
 off_t gftp_get_file_size 		( gftp_request * request, 
 					  const char *filename );
 
-int gftp_need_proxy 			( gftp_request * request,
-					  char *service );
-
-char *gftp_convert_ascii 		( char *buf, 
-					  ssize_t *len, 
-					  int direction );
-
 void gftp_calc_kbs 			( gftp_transfer * tdata, 
 				 	  ssize_t num_read );
 
@@ -801,20 +769,12 @@
 					  void (*update_func) 
 						( gftp_transfer * transfer ));
 
-int gftp_get_file_transfer_mode 	( char *filename,
-					  int def );
-
 int gftp_connect_server 		( gftp_request * request, 
-					  char *service );
+					  char *service,
+					  char *proxy_hostname,
+					  int proxy_port );
 
-void gftp_set_sftpserv_path		( gftp_request * request,
-					  char *path );
-
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-
-int get_port 				( struct addrinfo *addr );
-
-#else
+#if !defined (HAVE_GETADDRINFO) || !defined (HAVE_GAI_STRERROR)
 
 struct hostent *r_gethostbyname 	( const char *name, 
 					  struct hostent *result_buf, 
@@ -826,6 +786,7 @@
 					  const char *proto,
 					  struct servent *result_buf, 
 					  int *h_errnop );
+
 void gftp_set_config_options 		( gftp_request * request );
 
 void print_file_list 			( GList * list );
@@ -858,5 +819,8 @@
 void gftp_swap_socks 			( gftp_request * dest, 
 					  gftp_request * source );
 
+void gftp_calc_kbs 			( gftp_transfer * tdata, 
+					  ssize_t num_read );
+
 #endif
 
--- a/lib/local.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/local.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  local.c - functions that will use the local system                       */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -632,6 +632,12 @@
 }
 
 
+void 
+local_register_module (void)
+{
+}
+
+
 void
 local_init (gftp_request * request)
 {
@@ -653,7 +659,6 @@
   request->abort_transfer = local_end_transfer; /* NOTE: uses end_transfer */
   request->list_files = local_list_files;
   request->get_next_file = local_get_next_file;
-  request->set_data_type = NULL;
   request->get_file_size = local_get_file_size;
   request->chdir = local_chdir;
   request->rmdir = local_rmdir;
@@ -667,7 +672,6 @@
   request->set_config_options = NULL;
   request->swap_socks = NULL;
   request->url_prefix = "file";
-  request->protocol_name = "Local";
   request->need_hostport = 0;
   request->need_userpass = 0;
   request->use_cache = 0;
--- a/lib/misc.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/misc.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  misc.c - general purpose routines                                        */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -347,7 +347,7 @@
       else if (strcmp (argv[0][1], "--version") == 0 || 
                strcmp (argv[0][1], "-v") == 0)
 	{
-	  printf ("%s\n", version);
+	  printf ("%s\n", gftp_version);
 	  exit (0);
 	}
     }
@@ -530,10 +530,6 @@
 void
 free_tdata (gftp_transfer * tdata)
 {
-  if (tdata->statmutex)
-    g_free (tdata->statmutex);
-  if (tdata->structmutex)
-    g_free (tdata->structmutex);
   if (tdata->fromreq != NULL)
     gftp_request_destroy (tdata->fromreq, 1);
   if (tdata->toreq != NULL)
@@ -561,19 +557,9 @@
   if (req->directory)
     newreq->directory = g_strdup (req->directory);
   newreq->port = req->port;
-  newreq->data_type = req->data_type;
   newreq->use_proxy = req->use_proxy;
-  gftp_set_proxy_config (newreq, req->proxy_config);
-  newreq->transfer_type = req->transfer_type;
-  newreq->network_timeout = req->network_timeout;
-  newreq->retries = req->retries;
-  newreq->sleep_time = req->sleep_time;
-  newreq->passive_transfer = req->passive_transfer;
-  newreq->maxkbs = req->maxkbs;
   newreq->logging_function = req->logging_function;
-
-  if (req->sftpserv_path != NULL)
-    newreq->sftpserv_path = g_strdup (req->sftpserv_path);
+  newreq->local_options = NULL; /* FIXME */
 
   req->init (newreq);
 
@@ -716,248 +702,6 @@
 }
 
 
-/* We have the caller send us a pointer to a string so we can write the port
-   into it. It makes it easier so we don't have to worry about freeing it 
-   later on, the caller can just send us an auto variable, The string
-   should be at least 6 chars. I know this is messy... */
-
-char **
-make_ssh_exec_args (gftp_request * request, char *execname, 
-                    int use_sftp_subsys, char *portstring)
-{
-  char **args, *oldstr, *tempstr;
-  struct servent serv_struct;
-  int i, j;
-
-  args = g_malloc (sizeof (char *) * (num_ssh_extra_params + 15));
-
-  args[0] = ssh_prog_name != NULL && *ssh_prog_name != '\0' ? 
-            ssh_prog_name : "ssh";
-  i = 1;
-  tempstr = g_strdup (args[0]);
-
-  if (ssh_extra_params_list != NULL)
-    {
-      for (j=0; ssh_extra_params_list[j] != NULL; j++)
-        {
-          oldstr = tempstr;
-          args[i++] = ssh_extra_params_list[j];
-          tempstr = g_strconcat (oldstr, " ", ssh_extra_params_list[j], NULL);
-          g_free (oldstr);
-        }
-    }
-
-  oldstr = tempstr;
-  tempstr = g_strconcat (oldstr, " -e none", NULL);
-  g_free (oldstr);
-  args[i++] = "-e";
-  args[i++] = "none";
-
-  if (request->username && *request->username != '\0')
-    {
-      oldstr = tempstr;
-      tempstr = g_strconcat (oldstr, " -l ", request->username, NULL);
-      g_free (oldstr);
-      args[i++] = "-l";
-      args[i++] = request->username;
-    }
-
-  if (request->port != 0)
-    {
-      g_snprintf (portstring, 6, "%d", request->port);
-      oldstr = tempstr;
-      tempstr = g_strconcat (oldstr, " -p ", portstring, NULL);
-      g_free (oldstr);
-      args[i++] = "-p";
-      args[i++] = portstring;
-    }
-  else
-    {
-      if (!r_getservbyname ("ssh", "tcp", &serv_struct, NULL))
-        request->port = 22;
-      else
-        request->port = ntohs (serv_struct.s_port);
-    }
-
-  if (use_sftp_subsys)
-    {
-      oldstr = tempstr;
-      tempstr = g_strconcat (oldstr, " ", request->hostname, " -s sftp", NULL);
-      g_free (oldstr);
-      args[i++] = request->hostname;
-      args[i++] = "-s";
-      args[i++] = "sftp";
-      args[i] = NULL;
-    }
-  else
-    {
-      oldstr = tempstr;
-      tempstr = g_strconcat (oldstr, " ", request->hostname, " \"", execname, 
-                             "\"", NULL);
-      g_free (oldstr);
-      args[i++] = request->hostname;
-      args[i++] = execname;
-      args[i] = NULL;
-    }
-
-  request->logging_function (gftp_logging_misc, request->user_data, 
-                             _("Running program %s\n"), tempstr);
-  g_free (tempstr);
-  return (args);
-}
-
-#define SSH_LOGIN_BUFSIZE	200
-#define SSH_ERROR_BADPASS	-1
-#define SSH_ERROR_QUESTION	-2
-#define SSH_WARNING 		-3
-
-char *
-ssh_start_login_sequence (gftp_request * request, int fd)
-{
-  char *tempstr, *pwstr, *tmppos;
-  size_t rem, len, diff, lastdiff, key_pos;
-  int wrotepw, ok;
-  ssize_t rd;
-
-  rem = len = SSH_LOGIN_BUFSIZE;
-  tempstr = g_malloc0 (len + 1);
-  key_pos = diff = lastdiff = 0;
-  wrotepw = 0;
-  ok = 1;
-
-  if (gftp_set_sockblocking (request, fd, 1) == -1)
-    return (NULL);
-
-  pwstr = g_strconcat (request->password, "\n", NULL);
-
-  errno = 0;
-  while (1)
-    {
-      if ((rd = gftp_read (request, tempstr + diff, rem - 1, fd)) <= 0)
-        {
-          ok = 0;
-          break;
-        }
-      rem -= rd;
-      diff += rd;
-      tempstr[diff] = '\0'; 
-
-      if (diff > 11 && strcmp (tempstr + diff - 10, "password: ") == 0)
-        {
-          if (wrotepw)
-            {
-              ok = SSH_ERROR_BADPASS;
-              break;
-            }
-
-          if (strstr (tempstr, "WARNING") != NULL ||
-              strstr (tempstr, _("WARNING")) != NULL)
-            {
-              ok = SSH_WARNING;
-              break;
-            }
-              
-          wrotepw = 1;
-          if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0)
-            {
-              ok = 0;
-              break;
-            }
-        }
-      else if (diff > 2 && strcmp (tempstr + diff - 2, ": ") == 0 &&
-               ((tmppos = strstr (tempstr + key_pos, "Enter passphrase for RSA key")) != NULL ||
-                ((tmppos = strstr (tempstr + key_pos, "Enter passphrase for key '")) != NULL)))
-        {
-          key_pos = diff;
-          if (wrotepw)
-            {
-              ok = SSH_ERROR_BADPASS;
-              break;
-            }
-
-          if (strstr (tempstr, "WARNING") != NULL ||
-              strstr (tempstr, _("WARNING")) != NULL)
-            {
-              ok = SSH_WARNING;
-              break;
-            }
-
-          wrotepw = 1;
-          if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0)
-            {
-              ok = 0;
-              break;
-            }
-        }
-      else if (diff > 10 && strcmp (tempstr + diff - 10, "(yes/no)? ") == 0)
-        {
-          ok = SSH_ERROR_QUESTION;
-          break;
-        }
-      else if (diff >= 5 && strcmp (tempstr + diff - 5, "xsftp") == 0)
-        break;
-      else if (rem <= 1)
-        {
-          request->logging_function (gftp_logging_recv, request->user_data,
-                                     "%s", tempstr + lastdiff);
-          len += SSH_LOGIN_BUFSIZE;
-          rem += SSH_LOGIN_BUFSIZE;
-          lastdiff = diff;
-          tempstr = g_realloc (tempstr, len);
-          continue;
-        }
-    }
-
-  g_free (pwstr);
-
-  if (*(tempstr + lastdiff) != '\0')
-    request->logging_function (gftp_logging_recv, request->user_data,
-                               "%s\n", tempstr + lastdiff);
-
-  if (ok <= 0)
-    {
-      if (ok == SSH_ERROR_BADPASS)
-        request->logging_function (gftp_logging_error, request->user_data,
-                               _("Error: An incorrect password was entered\n"));
-      else if (ok == SSH_ERROR_QUESTION)
-        request->logging_function (gftp_logging_error, request->user_data,
-                               _("Please connect to this host with the command line SSH utility and answer this question appropriately.\n"));
-      else if (ok == SSH_WARNING)
-        request->logging_function (gftp_logging_error, request->user_data,
-                                   _("Please correct the above warning to connect to this host.\n"));
-
-      g_free (tempstr);
-      return (NULL);
-    }
- 
-  return (tempstr);
-}
-
-
-#ifdef G_HAVE_GINT64
-
-gint64
-hton64 (gint64 val)
-{
-  gint64 num;
-  char *pos;
-
-  num = 0;
-  pos = (char *) &num;
-  pos[0] = (val >> 56) & 0xff;
-  pos[1] = (val >> 48) & 0xff;
-  pos[2] = (val >> 40) & 0xff;
-  pos[3] = (val >> 32) & 0xff;
-  pos[4] = (val >> 24) & 0xff;
-  pos[5] = (val >> 16) & 0xff;
-  pos[6] = (val >> 8) & 0xff;
-  pos[7] = val & 0xff;
-  return (num);
-}
-
-#endif
-
-
 static gint
 gftp_file_sort_function_as (gconstpointer a, gconstpointer b)
 {
@@ -1124,6 +868,7 @@
   GList * files, * dirs, * dotdot, * tempitem, * insitem;
   GCompareFunc sortfunc;
   gftp_file * tempfle;
+  int sort_dirs_first;
 
   files = dirs = dotdot = NULL;
 
@@ -1138,9 +883,15 @@
                 gftp_group_sort_function_as : gftp_group_sort_function_ds;
   else if (column == GFTP_SORT_COL_DATETIME)
     sortfunc = asds ?
-                gftp_datetime_sort_function_as : gftp_datetime_sort_function_ds;  else /* GFTP_SORT_COL_ATTRIBS */
+                gftp_datetime_sort_function_as : gftp_datetime_sort_function_ds;
+  else if (column == GFTP_SORT_COL_ATTRIBS)
     sortfunc = asds ? 
                 gftp_attribs_sort_function_as : gftp_attribs_sort_function_ds;
+  else /* Don't sort */
+   return (filelist);
+
+  sort_dirs_first = 1;
+  gftp_lookup_global_option ("sort_dirs_first", &sort_dirs_first);
 
   for (tempitem = filelist; tempitem != NULL; )
     {
--- a/lib/options.h	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/options.h	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  options.h - the global variables for the program                         */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -21,17 +21,7 @@
 
 #include "gftp.h"
 
-supported_gftp_protocols gftp_protocols[] =
-{
-  {"FTP", 	rfc959_init, 	"ftp",		1},
-  {"HTTP", 	rfc2068_init, 	"http",		1},
-  {"Local", 	local_init, 	"file",		1},
-  {"SSH2",	sshv2_init,	"ssh2", 	1},
-  {"Bookmark", 	bookmark_init, 	"bookmark", 	0},
-  {NULL, 	NULL, 		NULL,		0}
-};
-
-gftp_proxy_type proxy_type[] = {
+gftp_proxy_type_var gftp_proxy_type[] = {
   {N_("none"), ""},
   {N_("SITE command"), "USER %pu\nPASS %pp\nSITE %hh\nUSER %hu\nPASS %hp\n"},
   {N_("user@host"), "USER %pu\nPASS %pp\nUSER %hu@%hh\nPASS %hp\n"},
@@ -44,112 +34,182 @@
   {NULL, NULL}
 };
 
-/* Most of these should be self explanatory */
-char version[] = "gFTP " VERSION,
-     *emailaddr = NULL,			/* Email address for logging in
-                                           anonymously */
-     *default_protocol = NULL,
-     *edit_program = NULL,
-     *view_program = NULL,
-     *firewall_host = NULL,
-     *firewall_username = NULL,
-     *firewall_password = NULL,
-     *firewall_account = NULL,
-     *proxy_config = NULL, 		/* The way to log into the proxy */
-     *http_proxy_host = NULL,
-     *http_proxy_username = NULL, 
-     *http_proxy_password = NULL,
-     *startup_directory = NULL,
-     *ssh_prog_name = NULL,
-     *ssh_extra_params = NULL,
-     **ssh_extra_params_list = NULL,
-     *ssh2_sftp_path = NULL;
-int num_ssh_extra_params;
+static char *gftp_sort_columns[] = { N_("none"), N_("file"), N_("size"), 
+                                     N_("user"), N_("group"), 
+                                     N_("datetime"), N_("attribs"), NULL };
+
+static char *gftp_sort_direction[] = { N_("descending"), N_("ascending"), NULL };
+
+static float gftp_maxkbs = 0.0;
+
+gftp_config_vars gftp_global_config_vars[] =
+{
+  {"", N_("General"), gftp_option_type_notebook, NULL, 
+   NULL, GFTP_PORT_GTK, NULL},
+
+  {"view_program", N_("View program:"), gftp_option_type_text, "", NULL, 0,
+   N_("The default program used to view files. If this is blank, the internal file viewer will be used"), 
+   GFTP_PORT_GTK, NULL},
+  {"edit_program", N_("Edit program:"), gftp_option_type_text, "", NULL, 0,
+   N_("The default program used to edit files."), GFTP_PORT_GTK, NULL},
+  {"startup_directory", N_("Startup Directory:"), 
+   gftp_option_type_text, "", NULL, 0,
+   N_("The default directory gFTP will go to on startup"), GFTP_PORT_ALL, NULL},
+  {"max_log_window_size", N_("Max Log Window Size:"), 
+   gftp_option_type_int, 0, NULL, 0, 
+   N_("The maximum size of the log window in bytes for the GTK+ port"), 
+   GFTP_PORT_GTK, NULL},
 
-FILE * logfd = NULL;			/* Our fd to write logs to */
+  {"append_transfers", N_("Append file transfers"), 
+  gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 0,
+   N_("Append new file transfers onto existing ones"), GFTP_PORT_GTK, NULL},
+  {"one_transfer", N_("Do one transfer at a time"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, 0,
+   N_("Do only one transfer at a time?"), GFTP_PORT_GTK, NULL},
+  {"overwrite_default", N_("Overwrite by Default"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, 0,
+   N_("Overwrite files by default or set to resume file transfers"), 
+   GFTP_PORT_GTK, NULL},
+  {"refresh_files", N_("Refresh after each file transfer"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, 0,
+   N_("Refresh the listbox after each file is transfered"), GFTP_PORT_GTK,
+   NULL},
+  {"sort_dirs_first", N_("Sort directories first"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 0,
+   N_("Put the directories first then the files"), GFTP_PORT_ALL, NULL},
+  {"show_hidden_files", N_("Show hidden files"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 0,
+   N_("Show hidden files in the listboxes"), GFTP_PORT_ALL, NULL},
 
-double maxkbs = 0.00;			/* Bandwidth throttling */
-GList * proxy_hosts = NULL, 		/* Our local hosts that won't need to 
-                                           use the proxy */
-      * registered_exts = NULL,		/* Registered file extensions */
-      * viewedit_processes = NULL,      /* View/Edit processes that are 
-                                           running */
-      * file_transfers = NULL,		/* File transfers in progress */
-      * file_transfer_logs = NULL;	/* Logs generated by other threads */
-
-gftp_bookmarks * bookmarks = NULL;
-GHashTable * bookmarks_htable = NULL,
-           * config_htable = NULL;
+  {"", N_("Network"), gftp_option_type_notebook, NULL, NULL, 0,
+   NULL, GFTP_PORT_GTK, NULL},
+  {"network_timeout", N_("Network timeout:"), 
+   gftp_option_type_int, GINT_TO_POINTER(60), NULL, 0,
+   N_("The timeout waiting for network input/output. This is NOT an idle timeout."), 
+   GFTP_PORT_ALL, NULL},
+  {"retries", N_("Connect retries:"), 
+   gftp_option_type_int, GINT_TO_POINTER(3), NULL, 0,
+   N_("The number of auto-retries to do. Set this to 0 to retry indefinately"), 
+   GFTP_PORT_ALL, NULL},
+  {"sleep_time", N_("Retry sleep time:"), 
+   gftp_option_type_int, GINT_TO_POINTER(30), NULL, 0,
+   N_("The number of seconds to wait between retries"), GFTP_PORT_ALL, NULL},
+  {"maxkbs", N_("Max KB/S:"), 
+   gftp_option_type_float, &gftp_maxkbs, NULL, 0,
+   N_("The maximum KB/s a file transfer can get. (Set to 0 to disable)"),  
+   GFTP_PORT_ALL, NULL},
+/* FIXME
+ {"", N_("Default Protocol"), (void *) 0x1, CONFIG_COMBO, "DP", NULL, GFTP_PORT_GTK},
+  {"default_protocol", N_("Default Protocol"), &default_protocol, 
+        CONFIG_CHARTEXT, N_("This specifies the default protocol to use"), NULL, 0},
 
-int do_one_transfer_at_a_time = 1, 	/* Only allow one transfer at a time. 
-                                           The other transfers will be queued */
-    start_file_transfers = 1, 		/* Shall we start the file transfers? */
-    transfer_in_progress = 0, 		/* Any transfers transferring files? */
-    passive_transfer = 1, 		/* Are we sending PASV or PORT to the 
-					   server */
-    sort_dirs_first = 1, 		/* Put the dirs first when sorting */
-    show_hidden_files = 1, 		/* Show hidden files */
-    refresh_files = 0, 			/* Refresh the listbox after each file 
-                                           is done */
-    listbox_local_width = 302, 		/* Width of the local listbox */
-    listbox_remote_width = 302, 	/* Width of the remote listbox */
-    listbox_file_height = 265, 		/* Height of the local/remote listbox */
-    transfer_height = 80, 		/* Height of the transfer window */
-    log_height = 105, 			/* Height of the logging window */
-    retries = 3, 			/* Number of auto-retries */
-    sleep_time = 30, 			/* Number of seconds to wait between 
-					   retries */
-    network_timeout = 120, 		/* Timeout on the read()s and write()s */
-    use_http11 = 1, 			/* Use HTTP/1.1 or HTTP/1.0 */
-    listbox_dblclick_action = 0, 	/* What happens when you double click in the
-					   file listboxes. 0 = View, 1 = Edit,
-					   2 = Download */
-    file_trans_column = 100, 		/* The width of the File column in the 
-					   listbox */
-    local_columns[6] = {0, 85, 75, 76, 120, 75}, /* The width of the local
-    	file, size, user, group, date and attribs column */
-    remote_columns[6] = {0, 85, 75, 76, 120, 75}, /* The width of the remote
-    	file, size, user, group, date and attribs column */
-    resolve_symlinks = 1, 		/* Send LIST -L or LIST to the remote ftp 
-					   server */
-    firewall_port = 21, 		/* What port to connect to for ftp? */
-    http_proxy_port = 80,		/* What port to connect to for http? */
-    overwrite_by_default = 0,		/* Resume file transfers or set to
-                                           overwrite by default */
-    append_file_transfers = 1,		/* Append new file transfers onto 
-                                           existing ones for the same 
-                                           hostname */
-    ssh_need_userpass = 0,		/* Require a user/pass for SSH
-                                           connections */
-    ssh_use_askpass = 0,		/* Use the ssh-askpass tool to
-					   grab the password. I personally
-					   don't like this, but some people
-					   do */
-    sshv2_use_sftp_subsys = 0,		/* Call ssh -s sftp. If you set this
-					   it'll automatically use the askpass
-					   utility above */
-    local_sortcol = 1,			
-    local_sortasds = 1,
-    remote_sortcol = 1,
-    remote_sortasds = 1;
+*/
+  {"list_dblclk_action", "", 
+   gftp_option_type_int, GINT_TO_POINTER(0), NULL, 0,
+   N_("This defines what will happen when you double click a file in the file listboxes. 0=View file 1=Edit file 2=Transfer file"), 0, NULL},
+  {"listbox_local_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(302), NULL, 0,
+   N_("The default width of the local files listbox"), 0, NULL},
+  {"listbox_remote_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(302), NULL, 0,
+   N_("The default width of the remote files listbox"), 0, NULL},
+  {"listbox_file_height", "",
+   gftp_option_type_int, GINT_TO_POINTER(265), NULL, 0,
+   N_("The default height of the local/remote files listboxes"), 0, NULL},
+  {"transfer_height", "", 
+   gftp_option_type_int, GINT_TO_POINTER(80), NULL, 0,
+   N_("The default height of the transfer listbox"), 0, NULL},
+  {"log_height", "", 
+   gftp_option_type_int, GINT_TO_POINTER(105), NULL, 0,
+   N_("The default height of the logging window"), 0, NULL},
+  {"file_trans_column", "", 
+   gftp_option_type_int, GINT_TO_POINTER(100), NULL, 0,
+   N_("The width of the filename column in the transfer window. Set this to 0 to have this column automagically resize."), 0, NULL},
+
+  {"local_sortcol", "", 
+   gftp_option_type_intcombo, GINT_TO_POINTER(1), gftp_sort_columns, 0,
+   N_("The default column to sort by"), GFTP_PORT_TEXT, NULL},
+  {"local_sortasds", "", 
+   gftp_option_type_intcombo, GINT_TO_POINTER(1), gftp_sort_direction, 0,
+   N_("Sort ascending or descending"), GFTP_PORT_TEXT, NULL},
+  {"remote_sortcol", "", 
+   gftp_option_type_intcombo, GINT_TO_POINTER(1), gftp_sort_columns, 0,
+   N_("The default column to sort by"), GFTP_PORT_TEXT, NULL},
+  {"remote_sortasds", "", 
+   gftp_option_type_intcombo, GINT_TO_POINTER(1), gftp_sort_direction, 0,
+   N_("Sort ascending or descending"), GFTP_PORT_TEXT, NULL},
 
-
-guint max_log_window_size = 5000;	/* Max size of the log window for the 
-                                           GTK port */
+  {"local_file_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(0), NULL, 0,
+   N_("The width of the filename column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"local_size_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(85), NULL, 0,
+   N_("The width of the size column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"local_user_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(75), NULL, 0,
+   N_("The width of the user column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"local_group_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(76), NULL, 0,
+   N_("The width of the group column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"local_date_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(120), NULL, 0,
+   N_("The width of the date column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"local_attribs_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(75), NULL, 0,
+   N_("The width of the attribs column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"remote_file_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(0), NULL, 0,
+   N_("The width of the filename column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"remote_size_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(85), NULL, 0,
+   N_("The width of the size column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"remote_user_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(75), NULL, 0,
+   N_("The width of the user column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"remote_group_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(76), NULL, 0,
+   N_("The width of the group column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"remote_date_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(120), NULL, 0,
+   N_("The width of the date column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"remote_attribs_width", "", 
+   gftp_option_type_int, GINT_TO_POINTER(75), NULL, 0,
+   N_("The width of the attribs column in the file listboxes. Set this to 0 to have this column automagically resize. Set this to -1 to disable this column"), 0, NULL},
+  {"send_color", "", 
+   gftp_option_type_color, "0:8600:0", NULL, 0,
+   N_("The color of the commands that are sent to the server"), 0, NULL},
+  {"recv_color", "", 
+   gftp_option_type_color, "0:0:ffff", NULL, 0,
+   N_("The color of the commands that are received from the server"), 0, NULL},
+  {"error_color", "", 
+   gftp_option_type_color, "ffff:0:0", NULL, 0,
+   N_("The color of the error messages"), 0, NULL},
+  {"misc_color", "", 
+   gftp_option_type_color, "a000:8d00:4600", NULL, 0,
+   N_("The color of the rest of the log messages"), 0, NULL}
+};
 
-GList * host_history = NULL,
-      * port_history = NULL,
-      * user_history = NULL,
-      * localhistory = NULL,
-      * remotehistory = NULL;
+supported_gftp_protocols gftp_protocols[] =
+{
+  {N_("FTP"), rfc959_init, rfc959_register_module, "ftp", 1},
+  {N_("HTTP"), rfc2068_init, rfc2068_register_module, "http", 1},
+  {N_("Local"), local_init, local_register_module, "file", 1},
+  {N_("SSH2"), sshv2_init, sshv2_register_module, "ssh2", 1},
+  {N_("Bookmark"), bookmark_init, bookmark_register_module, "bookmark", 0},
+  {NULL, NULL, NULL, NULL, 0}
+};
+
+GHashTable * gftp_global_options_htable = NULL, 	
+           * gftp_config_list_htable = NULL,
+           * gftp_bookmarks_htable = NULL;
+
+char gftp_version[] = "gFTP " VERSION;
+
+GList * gftp_file_transfers = NULL, 
+      * gftp_file_transfer_logs = NULL,
+      * gftp_options_list = NULL;
       
-unsigned int host_len = 0, 
-             port_len = 0, 
-             user_len = 0,
-             localhistlen = 0,
-             remotehistlen = 0;
+gftp_bookmarks_var * gftp_bookmarks = NULL;
 
-volatile sig_atomic_t viewedit_process_done = 0;
+FILE * gftp_logfd = NULL;
 
-gftp_color send_color, recv_color, error_color, misc_color;
-
--- a/lib/protocols.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/protocols.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  protocols.c - Skeleton functions for the protocols gftp supports         */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -20,6 +20,7 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
+/* {{{ gftp_request_new */
 gftp_request *
 gftp_request_new (void)
 {
@@ -29,11 +30,10 @@
   request->sockfd = -1;
   request->datafd = -1;
   request->cachefd = -1;
-  request->data_type = GFTP_TYPE_BINARY;
-  request->server_type = GFTP_TYPE_OTHER;
+  request->server_type = GFTP_DIRTYPE_OTHER;
   return (request);
 }
-
+/* }}} */
 
 void
 gftp_request_destroy (gftp_request * request, int free_request)
@@ -61,22 +61,10 @@
     }
   if (request->directory)
     g_free (request->directory);
-  if (request->proxy_config)
-    g_free (request->proxy_config);
-  if (request->proxy_hostname)
-    g_free (request->proxy_hostname);
-  if (request->proxy_username)
-    g_free (request->proxy_username);
-  if (request->proxy_password)
-    g_free (request->proxy_password);
-  if (request->proxy_account)
-    g_free (request->proxy_account);
   if (request->last_ftp_response)
     g_free (request->last_ftp_response);
   if (request->protocol_data)
     g_free (request->protocol_data);
-  if (request->sftpserv_path)
-    g_free (request->sftpserv_path);
 
   memset (request, 0, sizeof (*request));
 
@@ -87,8 +75,8 @@
       request->sockfd = -1;
       request->datafd = -1;
       request->cachefd = -1;
-      request->data_type = GFTP_TYPE_BINARY;
     }
+  /* FIXME - free local_options */
 }
 
 
@@ -136,12 +124,6 @@
 #endif
   request->hostp = NULL;
 
-  if (request->sftpserv_path != NULL)
-    {
-      g_free (request->sftpserv_path);
-      request->sftpserv_path = NULL;
-    }
-
   request->cached = 0;
   if (request->disconnect == NULL)
     return;
@@ -153,8 +135,18 @@
 gftp_get_file (gftp_request * request, const char *filename, int fd,
                size_t startsize)
 {
+  float maxkbs;
+
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
 
+  gftp_lookup_request_option (request, "maxkbs", &maxkbs);
+  if (maxkbs > 0)
+    {
+      request->logging_function (gftp_logging_misc, request->user_data,
+                    _("File transfer will be throttled to %.2f KB/s\n"),
+                    maxkbs);
+    }
+
   request->cached = 0;
   if (request->get_file == NULL)
     return (GFTP_EFATAL);
@@ -166,8 +158,19 @@
 gftp_put_file (gftp_request * request, const char *filename, int fd,
                size_t startsize, size_t totalsize)
 {
+  float maxkbs;
+
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
 
+  gftp_lookup_request_option (request, "maxkbs", &maxkbs);
+
+  if (maxkbs > 0)
+    {
+      request->logging_function (gftp_logging_misc, request->user_data,
+                    _("File transfer will be throttled to %.2f KB/s\n"), 
+                    maxkbs);
+    }
+
   request->cached = 0;
   if (request->put_file == NULL)
     return (GFTP_EFATAL);
@@ -377,7 +380,8 @@
 gftp_parse_bookmark (gftp_request * request, const char * bookmark)
 {
   gftp_logging_func logging_function;
-  gftp_bookmarks * tempentry;
+  gftp_bookmarks_var * tempentry;
+  char *default_protocol;
   int i;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
@@ -387,7 +391,8 @@
   gftp_request_destroy (request, 0);
   request->logging_function = logging_function;
 
-  if ((tempentry = g_hash_table_lookup (bookmarks_htable, bookmark)) == NULL)
+  if ((tempentry = g_hash_table_lookup (gftp_bookmarks_htable, 
+                                        bookmark)) == NULL)
     {
       request->logging_function (gftp_logging_error, request->user_data,
                                  _("Error: Could not find bookmark %s\n"), 
@@ -405,12 +410,7 @@
     gftp_set_username (request, tempentry->user);
 
   if (tempentry->pass != NULL)
-    {
-      if (strncmp (tempentry->pass, "@EMAIL@", 7) == 0)
-        gftp_set_password (request, emailaddr);
-      else
-        gftp_set_password (request, tempentry->pass);
-    }
+    gftp_set_password (request, tempentry->pass);
 
   if (tempentry->acct != NULL)
     gftp_set_account (request, tempentry->acct);
@@ -418,7 +418,6 @@
   gftp_set_hostname (request, tempentry->hostname);
   gftp_set_directory (request, tempentry->remote_dir);
   gftp_set_port (request, tempentry->port);
-  gftp_set_sftpserv_path (request, tempentry->sftpserv_path);
 
   for (i = 0; gftp_protocols[i].name; i++)
     {
@@ -429,12 +428,18 @@
         }
     }
 
-  if (!gftp_protocols[i].name)
+  if (gftp_protocols[i].name == NULL)
     {
-      for (i = 0; gftp_protocols[i].url_prefix; i++)
+      gftp_lookup_request_option (request, "default_protocol", 
+                                  &default_protocol);
+
+      if (*default_protocol != '\0')
         {
-          if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
-            break;
+          for (i = 0; gftp_protocols[i].url_prefix; i++)
+            {
+              if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
+                break;
+            }
         }
 
       if (gftp_protocols[i].url_prefix == NULL)
@@ -449,7 +454,7 @@
 int
 gftp_parse_url (gftp_request * request, const char *url)
 {
-  char *pos, *endpos, *endhostpos, *str, tempchar;
+  char *pos, *endpos, *endhostpos, *str, tempchar, *default_protocol;
   gftp_logging_func logging_function;
   const char *stpos;
   int len, i;
@@ -463,6 +468,8 @@
 
   for (stpos = url; *stpos == ' '; stpos++);
 
+  i = GFTP_FTP_NUM;
+
   if ((pos = strstr (stpos, "://")) != NULL)
     {
       *pos = '\0';
@@ -479,15 +486,21 @@
     }
   else
     {
-      for (i = 0; gftp_protocols[i].url_prefix; i++)
+      gftp_lookup_request_option (request, "default_protocol", 
+                                  &default_protocol);
+
+      if (*default_protocol != '\0')
         {
-          if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
-            break;
+          for (i = 0; gftp_protocols[i].url_prefix; i++)
+            {
+              if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
+                break;
+            }
         }
+    }
 
-      if (gftp_protocols[i].url_prefix == NULL)
-        i = GFTP_FTP_NUM;
-    }
+  if (gftp_protocols[i].url_prefix == NULL)
+    i = GFTP_FTP_NUM;
 
   gftp_protocols[i].init (request);
 
@@ -562,17 +575,6 @@
 }
 
 
-int
-gftp_set_data_type (gftp_request * request, int data_type)
-{
-  g_return_val_if_fail (request != NULL, GFTP_EFATAL);
-
-  if (request->set_data_type == NULL)
-    return (0);
-  return (request->set_data_type (request, data_type));
-}
-
-
 void
 gftp_set_hostname (gftp_request * request, const char *hostname)
 {
@@ -658,67 +660,6 @@
 }
 
 
-void
-gftp_set_proxy_hostname (gftp_request * request, const char *hostname)
-{
-  g_return_if_fail (request != NULL);
-  g_return_if_fail (hostname != NULL);
-
-  if (request->proxy_hostname)
-    g_free (request->proxy_hostname);
-  request->proxy_hostname = g_malloc (strlen (hostname) + 1);
-  strcpy (request->proxy_hostname, hostname);
-}
-
-
-void
-gftp_set_proxy_username (gftp_request * request, const char *username)
-{
-  g_return_if_fail (request != NULL);
-  g_return_if_fail (username != NULL);
-
-  if (request->proxy_username)
-    g_free (request->proxy_username);
-  request->proxy_username = g_malloc (strlen (username) + 1);
-  strcpy (request->proxy_username, username);
-}
-
-
-void
-gftp_set_proxy_password (gftp_request * request, const char *password)
-{
-  g_return_if_fail (request != NULL);
-  g_return_if_fail (password != NULL);
-
-  if (request->proxy_password)
-    g_free (request->proxy_password);
-  request->proxy_password = g_malloc (strlen (password) + 1);
-  strcpy (request->proxy_password, password);
-}
-
-
-void
-gftp_set_proxy_account (gftp_request * request, const char *account)
-{
-  g_return_if_fail (request != NULL);
-  g_return_if_fail (account != NULL);
-
-  if (request->proxy_account)
-    g_free (request->proxy_account);
-  request->proxy_account = g_malloc (strlen (account) + 1);
-  strcpy (request->proxy_account, account);
-}
-
-
-void
-gftp_set_proxy_port (gftp_request * request, unsigned int port)
-{
-  g_return_if_fail (request != NULL);
-
-  request->proxy_port = port;
-}
-
-
 int
 gftp_remove_directory (gftp_request * request, const char *directory)
 {
@@ -797,39 +738,6 @@
 }
 
 
-void
-gftp_set_proxy_config (gftp_request * request, const char *proxy_config)
-{
-  int len;
-
-  g_return_if_fail (request != NULL);
-
-  if (request->proxy_config != NULL)
-    g_free (request->proxy_config);
-
-  if (proxy_config == NULL)
-    {
-      request->proxy_config = NULL;
-      return;
-    }
-
-  len = strlen (proxy_config);
-
-  if (len > 0 && (proxy_config[len - 1] != 'n' ||
-		  proxy_config[len - 2] != '%'))
-    len += 2;
-
-  request->proxy_config = g_malloc (len + 1);
-  strcpy (request->proxy_config, proxy_config);
-  if (len != strlen (proxy_config))
-    {
-      request->proxy_config[len - 2] = '%';
-      request->proxy_config[len - 1] = 'n';
-      request->proxy_config[len] = '\0';
-    }
-}
-
-
 off_t
 gftp_get_file_size (gftp_request * request, const char *filename)
 {
@@ -841,9 +749,11 @@
 }
 
 
-int
-gftp_need_proxy (gftp_request * request, char *service)
+static int
+gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname, 
+                 int proxy_port)
 {
+  gftp_config_list_vars * proxy_hosts;
   gftp_proxy_hosts * hostname;
   unsigned char addy[4];
   struct sockaddr *addr;
@@ -854,20 +764,24 @@
   struct addrinfo hints;
   int port, errnum;
   char serv[8];
+#endif
+
+  gftp_lookup_global_option ("ext", &proxy_hosts);
+
+  if (proxy_hostname == NULL || *proxy_hostname == '\0')
+    return (0);
+  else if (proxy_hosts->list == NULL)
+    return (proxy_hostname != NULL && 
+            *proxy_hostname != '\0');
 
   request->hostp = NULL;
-  if (proxy_hosts == NULL)
-    return (request->proxy_hostname != NULL
-	    && *request->proxy_hostname != '\0'
-	    && request->proxy_config != NULL
-	    && *request->proxy_config != '\0');
-
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
   memset (&hints, 0, sizeof (hints));
   hints.ai_flags = AI_CANONNAME;
   hints.ai_family = AF_INET;
   hints.ai_socktype = SOCK_STREAM;
 
-  port = request->use_proxy ? request->proxy_port : request->port;
+  port = request->use_proxy ? proxy_port : request->port;
   if (port == 0)
     strcpy (serv, service);
   else
@@ -888,14 +802,6 @@
   addr = request->hostp->ai_addr;
 
 #else /* !HAVE_GETADDRINFO */
-
-  request->hostp = NULL;
-  if (proxy_hosts == NULL)
-    return (request->proxy_hostname != NULL
-            && *request->proxy_hostname != '\0'
-            && request->proxy_config != NULL
-            && *request->proxy_config != '\0');
-
   request->logging_function (gftp_logging_misc, request->user_data,
                              _("Looking up %s\n"), request->hostname);
 
@@ -912,7 +818,7 @@
 
 #endif /* HAVE_GETADDRINFO */
 
-  templist = proxy_hosts;
+  templist = proxy_hosts->list;
   while (templist != NULL)
     {
       hostname = templist->data;
@@ -937,48 +843,8 @@
 	}
       templist = templist->next;
     }
-  return (request->proxy_hostname != NULL && *request->proxy_hostname != '\0'
-	  && request->proxy_config != NULL && *request->proxy_config != '\0');
-}
 
-
-char *
-gftp_convert_ascii (char *buf, ssize_t *len, int direction)
-{
-  ssize_t i, j, newsize;
-  char *tempstr;
-
-  if (direction == GFTP_DIRECTION_DOWNLOAD)
-    {
-      for (i = 0, j = 0; i < *len; i++)
-        {
-          if (buf[i] != '\r')
-            buf[j++] = buf[i];
-          else
-            --*len;
-        }
-      tempstr = buf;
-    }
-  else
-    {
-      newsize = 0;
-      for (i = 0; i < *len; i++)
-        {
-          newsize++;
-          if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
-            newsize++;
-        }
-      tempstr = g_malloc (newsize);
-
-      for (i = 0, j = 0; i < *len; i++)
-        {
-          if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
-            tempstr[j++] = '\r';
-          tempstr[j++] = buf[i];
-        }
-      *len = newsize;
-    }
-  return (tempstr);
+  return (proxy_hostname != NULL && *proxy_hostname != '\0');
 }
 
 
@@ -1128,7 +994,7 @@
   fle->file = g_strdup (str);
 
   curpos = goto_next_token (curpos + 1);
-  fle->size = strtol (curpos, NULL, 10) * 512; /* FIXME - Is this correct? */
+  fle->size = strtol (curpos, NULL, 10) * 512; /* Is this correct? */
   curpos = goto_next_token (curpos);
 
   if ((fle->datetime = parse_time (curpos, &curpos)) == 0)
@@ -1264,8 +1130,8 @@
       startpos = goto_next_token (startpos);
     }
 
-  /* FIXME - make this GFTP_TYPE_CRAY */
-  if (request->server_type != GFTP_TYPE_UNIX)
+  /* FIXME - make this GFTP_DIRTYPE_CRAY */
+  if (request->server_type != GFTP_DIRTYPE_UNIX)
     {
       /* See if this is a Cray directory listing. It has the following format:
       drwx------     2 feiliu    g913     DK  common      4096 Sep 24  2001 wv */
@@ -1419,19 +1285,20 @@
 
   switch (request->server_type)
     {
-      case GFTP_TYPE_UNIX:
-	result = gftp_parse_ls_unix (request, str, fle);
+      case GFTP_DIRTYPE_CRAY:
+      case GFTP_DIRTYPE_UNIX:
+        result = gftp_parse_ls_unix (request, str, fle);
         break;
-      case GFTP_TYPE_EPLF:
+      case GFTP_DIRTYPE_EPLF:
         result = gftp_parse_ls_eplf (str, fle);
         break;
-      case GFTP_TYPE_NOVELL:
+      case GFTP_DIRTYPE_NOVELL:
         result = gftp_parse_ls_novell (str, fle);
         break;
-      case GFTP_TYPE_DOS:
+      case GFTP_DIRTYPE_DOS:
         result = gftp_parse_ls_nt (str, fle);
         break;
-      case GFTP_TYPE_VMS:
+      case GFTP_DIRTYPE_VMS:
         result = gftp_parse_ls_vms (str, fle);
         break;
       default: /* autodetect */
@@ -1673,11 +1540,7 @@
             transfer->toreq->directory = oldtodir;
         }
       else
-        {
-          curfle->ascii = gftp_get_file_transfer_mode (curfle->file, 
-                              transfer->fromreq->data_type) == GFTP_TYPE_ASCII;
-          transfer->numfiles++;
-        }
+        transfer->numfiles++;
     }
 
   if (forcecd)
@@ -1694,36 +1557,8 @@
 }
 
 
-int
-gftp_get_file_transfer_mode (char *filename, int def)
-{
-  gftp_file_extensions * tempext;
-  GList * templist;
-  int stlen, ret;
-
-  ret = def;
-  stlen = strlen (filename);
-  for (templist = registered_exts; templist != NULL; templist = templist->next)
-    {
-      tempext = templist->data;
-
-      if (stlen >= tempext->stlen &&
-          strcmp (&filename[stlen - tempext->stlen], tempext->ext) == 0)
-        {
-          if (toupper (*tempext->ascii_binary == 'A'))
-            ret = GFTP_TYPE_ASCII;
-          else if (toupper (*tempext->ascii_binary == 'B'))
-            ret = GFTP_TYPE_BINARY;
-          break;
-        }
-    }
-
-  return (ret);
-}
-
-
 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-int
+static int
 get_port (struct addrinfo *addr)
 {
   struct sockaddr_in * saddr;
@@ -1743,7 +1578,8 @@
 
 
 int
-gftp_connect_server (gftp_request * request, char *service)
+gftp_connect_server (gftp_request * request, char *service,
+                     char *proxy_hostname, int proxy_port)
 {
   char *connect_host, *disphost;
   int port, sock;
@@ -1752,7 +1588,8 @@
   char serv[8];
   int errnum;
 
-  if ((request->use_proxy = gftp_need_proxy (request, service)) < 0)
+  if ((request->use_proxy = gftp_need_proxy (request, service,
+                                             proxy_hostname, proxy_port)) < 0)
     return (request->use_proxy);
   else if (request->use_proxy == 1)
     request->hostp = NULL;
@@ -1762,9 +1599,16 @@
   hints.ai_family = AF_INET;
   hints.ai_socktype = SOCK_STREAM;
 
-  connect_host = request->use_proxy ? request->proxy_hostname : 
-                                      request->hostname;
-  port = request->use_proxy ? request->proxy_port : request->port;
+  if (request->use_proxy)
+    {
+      connect_host = proxy_hostname;
+      port = proxy_port;
+    }
+  else
+    {
+      connect_host = request->hostname;
+      port = request->port;
+    }
 
   if (request->hostp == NULL)
     {
@@ -1831,7 +1675,8 @@
   struct servent serv_struct;
   int curhost;
 
-  if ((request->use_proxy = gftp_need_proxy (request, service)) < 0)
+  if ((request->use_proxy = gftp_need_proxy (request, service,
+                                             proxy_hostname, proxy_port)) < 0)
     return (request->use_proxy);
   else if (request->use_proxy == 1)
     request->hostp = NULL;
@@ -1847,16 +1692,26 @@
   memset (&remote_address, 0, sizeof (remote_address));
   remote_address.sin_family = AF_INET;
 
-  connect_host = request->use_proxy ? request->proxy_hostname : 
-                                      request->hostname;
-  port = htons (request->use_proxy ? request->proxy_port : request->port);
+  if (request->use_proxy)
+    {
+      connect_host = proxy_hostname;
+      port = proxy_port;
+    }
+  else
+    {
+      connect_host = request->hostname;
+      port = request->port;
+    }
 
   if (port == 0)
     {
       if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
         {
-          port = htons (21);
-          request->port = 21;
+          request->logging_function (gftp_logging_error, request->user_data,
+                                     _("Cannot look up service name %s/tcp. Please check your services file\n"),
+                                     service);
+          close (sock);
+          return (GFTP_EFATAL);
         }
       else
         {
@@ -1928,35 +1783,12 @@
 void
 gftp_set_config_options (gftp_request * request)
 {
-  request->network_timeout = network_timeout;
-  request->retries = retries;
-  request->sleep_time = sleep_time;
-  request->maxkbs = maxkbs;
-
   if (request->set_config_options != NULL)
     request->set_config_options (request);
 }
 
 
 void
-gftp_set_sftpserv_path (gftp_request * request, char *path)
-{
-  g_return_if_fail (request != NULL);
-
-  if (request->sftpserv_path)
-    g_free (request->sftpserv_path);
-
-  if (path != NULL && *path != '\0')
-    {
-      request->sftpserv_path = g_malloc (strlen (path) + 1);
-      strcpy (request->sftpserv_path, path);
-    }
-  else
-    request->sftpserv_path = NULL;
-}
-
-
-void
 print_file_list (GList * list)
 {
   gftp_file * tempfle;
@@ -2096,20 +1928,20 @@
 ssize_t 
 gftp_read (gftp_request * request, void *ptr, size_t size, int fd)
 {
+  long network_timeout;
   struct timeval tv;
   fd_set fset;
   ssize_t ret;
 
+  gftp_lookup_request_option (request, "network_timeout", &network_timeout);  
+
   errno = 0;
   ret = 0;
   do
     {
       FD_ZERO (&fset);
       FD_SET (fd, &fset);
-      if (request != NULL)
-        tv.tv_sec = request->network_timeout;
-      else
-        tv.tv_sec = network_timeout;
+      tv.tv_sec = network_timeout;
       tv.tv_usec = 0;
       ret = select (fd + 1, &fset, NULL, NULL, &tv);
       if (ret == -1 && errno == EINTR)
@@ -2166,20 +1998,20 @@
 ssize_t 
 gftp_write (gftp_request * request, const char *ptr, size_t size, int fd)
 {
+  long network_timeout;
   struct timeval tv;
   size_t ret, w_ret;
   fd_set fset;
 
+  gftp_lookup_request_option (request, "network_timeout", &network_timeout);  
+
   errno = 0;
   ret = 0;
   do
     {
       FD_ZERO (&fset);
       FD_SET (fd, &fset);
-      if (request != NULL)
-        tv.tv_sec = request->network_timeout;
-      else
-        tv.tv_sec = network_timeout;
+      tv.tv_sec = network_timeout;
       tv.tv_usec = 0;
       ret = select (fd + 1, NULL, &fset, NULL, &tv);
       if (ret == -1 && errno == EINTR)
@@ -2307,3 +2139,67 @@
     dest->swap_socks (dest, source);
 }
 
+
+void
+gftp_calc_kbs (gftp_transfer * tdata, ssize_t num_read)
+{
+  unsigned long waitusecs;
+  double difftime, curkbs;
+  gftp_file * tempfle;
+  unsigned long toadd;
+  struct timeval tv;
+  float maxkbs;
+
+  gftp_lookup_request_option (tdata->fromreq, "maxkbs", &maxkbs);
+
+  gettimeofday (&tv, NULL);
+  if (g_thread_supported ())
+    g_static_mutex_lock (&tdata->statmutex);
+
+  tempfle = tdata->curfle->data;
+  tdata->trans_bytes += num_read;
+  tdata->curtrans += num_read;
+  tdata->stalled = 0;
+
+  difftime = (tv.tv_sec - tdata->starttime.tv_sec) + ((double) (tv.tv_usec - tdata->starttime.tv_usec) / 1000000.0);
+  if (difftime <= 0)
+    tdata->kbs = (double) tdata->trans_bytes / 1024.0;
+  else
+    tdata->kbs = (double) tdata->trans_bytes / 1024.0 / difftime;
+
+  difftime = (tv.tv_sec - tdata->lasttime.tv_sec) + ((double) (tv.tv_usec - tdata->lasttime.tv_usec) / 1000000.0);
+
+  if (difftime <= 0)
+    curkbs = (double) (num_read / 1024.0);
+  else
+    curkbs = (double) (num_read / 1024.0 / difftime);
+
+  if (maxkbs > 0 && curkbs > maxkbs)
+    {
+      waitusecs = (double) num_read / 1024.0 / maxkbs * 1000000.0 - difftime;
+
+      if (waitusecs > 0)
+        {
+          if (g_thread_supported ())
+            g_static_mutex_unlock (&tdata->statmutex);
+
+          difftime += ((double) waitusecs / 1000000.0);
+          usleep (waitusecs);
+
+          if (g_thread_supported ())
+            g_static_mutex_lock (&tdata->statmutex);
+        }
+    }
+
+  /* I don't call gettimeofday (&tdata->lasttime) here because this will use
+     less system resources. This will be close enough for what we need */
+  difftime += tdata->lasttime.tv_usec / 1000000.0;
+  toadd = (long) difftime;
+  difftime -= toadd;
+  tdata->lasttime.tv_sec += toadd;
+  tdata->lasttime.tv_usec = difftime * 1000000.0;
+
+  if (g_thread_supported ())
+    g_static_mutex_unlock (&tdata->statmutex);
+}
+
--- a/lib/rfc2068.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/rfc2068.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  rfc2068.c - General purpose routines for the HTTP protocol               */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -20,6 +20,30 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
+static gftp_config_vars config_vars[] =
+{
+  {"", N_("HTTP"), gftp_option_type_notebook, NULL, NULL, 0, NULL, 
+   GFTP_PORT_GTK, NULL},
+
+  {"http_proxy_host", N_("Proxy hostname:"), 
+   gftp_option_type_text, "", NULL, 0, 
+   N_("Firewall hostname"), GFTP_PORT_ALL, 0},
+  {"http_proxy_port", N_("Proxy port:"), 
+   gftp_option_type_int, GINT_TO_POINTER(80), NULL, 0,
+   N_("Port to connect to on the firewall"), GFTP_PORT_ALL, NULL},
+  {"http_proxy_username", N_("Proxy username:"), 
+   gftp_option_type_text, "", NULL, 0,
+   N_("Your firewall username"), GFTP_PORT_ALL, NULL},
+  {"http_proxy_password", N_("Proxy password:"), 
+   gftp_option_type_hidetext, "", NULL, 0,
+   N_("Your firewall password"), GFTP_PORT_ALL, NULL},
+
+  {"use_http11", N_("Use HTTP/1.1"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 0,
+   N_("Do you want to use HTTP/1.1 or HTTP/1.0"), GFTP_PORT_ALL, NULL},
+  {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
+};
+
 typedef struct rfc2068_params_tag
 {
   gftp_getline_buffer * rbuf;
@@ -125,7 +149,8 @@
 rfc2068_send_command (gftp_request * request, const char *command,
                       const char *extrahdr)
 {
-  char *tempstr, *str;
+  char *tempstr, *str, *proxy_hostname, *proxy_username, *proxy_password;
+  int proxy_port;
   ssize_t ret;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
@@ -133,7 +158,7 @@
   g_return_val_if_fail (command != NULL, GFTP_EFATAL);
 
   tempstr = g_strdup_printf ("%sUser-Agent: %s\nHost: %s\n", command,
-                             version, request->hostname);
+                             gftp_version, request->hostname);
 
   request->logging_function (gftp_logging_send, request->user_data,
                              "%s", tempstr);
@@ -144,11 +169,14 @@
   if (ret < 0)
     return (ret);
 
-  if (request->use_proxy && request->proxy_username != NULL &&
-      *request->proxy_username != '\0')
+  gftp_lookup_request_option (request, "http_proxy_host", &proxy_hostname);
+  gftp_lookup_request_option (request, "http_proxy_port", &proxy_port);
+  gftp_lookup_request_option (request, "http_proxy_username", &proxy_username);
+  gftp_lookup_request_option (request, "http_proxy_password", &proxy_password);
+
+  if (request->use_proxy && proxy_username != NULL && *proxy_username != '\0')
     {
-      tempstr = g_strconcat (request->proxy_username, ":", 
-                             request->proxy_password, NULL);
+      tempstr = g_strconcat (proxy_username, ":", proxy_password, NULL);
       str = base64_encode (tempstr);
       g_free (tempstr);
 
@@ -195,23 +223,28 @@
 static int
 rfc2068_connect (gftp_request * request)
 {
-  char *service;
+  rfc2068_params * params;
+  char *proxy_hostname;
+  int proxy_port;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL);
   g_return_val_if_fail (request->hostname != NULL, GFTP_EFATAL);
 
+  params = request->protocol_data;
+
   if (request->sockfd > 0)
     return (0);
 
-  service = request->use_proxy && request->proxy_config != NULL && 
-            *request->proxy_config != '\0' ? request->proxy_config : "http";
+  gftp_lookup_request_option (request, "http_proxy_host", &proxy_hostname);
+  gftp_lookup_request_option (request, "http_proxy_port", &proxy_port);
 
   if (request->url_prefix != NULL)
     g_free (request->url_prefix);
-  request->url_prefix = g_strdup (service);
+  request->url_prefix = g_strdup ("http"); /* FIXME _ can be FTP */
 
-  if ((request->sockfd = gftp_connect_server (request, service)) < 0)
+  if ((request->sockfd = gftp_connect_server (request, request->url_prefix, 
+                                              proxy_hostname, proxy_port)) < 0)
     return (GFTP_ERETRYABLE);
 
   if (request->directory && *request->directory == '\0')
@@ -253,31 +286,31 @@
 rfc2068_get_file (gftp_request * request, const char *filename, int fd,
                   off_t startsize)
 {
-  char *tempstr, *extrahdr, *pos, *proto;
-  int restarted, ret;
+  char *tempstr, *extrahdr, *pos;
+  int restarted, ret, use_http11;
+  rfc2068_params * params;
   off_t size;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL);
   g_return_val_if_fail (filename != NULL, GFTP_EFATAL);
 
+  params = request->protocol_data;
+
+  gftp_lookup_request_option (request, "use_http11", &use_http11);
+
   if (fd > 0)
     request->sockfd = fd;
 
   if (request->sockfd < 0 && (ret = rfc2068_connect (request)) != 0)
     return (ret);
 
-  if (request->proxy_config != NULL && *request->proxy_config != '\0')
-    proto = request->proxy_config;
-  else
-    proto = "http";
-
   if (request->username == NULL || *request->username == '\0')
-    tempstr = g_strconcat ("GET ", proto, "://", 
+    tempstr = g_strconcat ("GET ", request->url_prefix, "://", 
                      request->hostname, "/", filename, 
                      use_http11 ? " HTTP/1.1\n" : " HTTP/1.0\n", NULL);
   else 
-    tempstr = g_strconcat ("GET ", proto, "://", 
+    tempstr = g_strconcat ("GET ", request->url_prefix, "://", 
                      request->username, "@", request->hostname, "/", filename, 
                      use_http11 ? " HTTP/1.1\n" : " HTTP/1.0\n", NULL);
 
@@ -379,30 +412,28 @@
 static int
 rfc2068_list_files (gftp_request * request)
 {
-  char *tempstr, *pos, *proto;
   rfc2068_params *params;
+  char *tempstr, *pos;
+  int r, use_http11;
   off_t ret;
-  int r;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL);
 
   params = request->protocol_data;
+  gftp_lookup_request_option (request, "use_http11", &use_http11);
+
   if (request->sockfd < 0 && (r = rfc2068_connect (request)) < 0)
     return (r);
 
-  if (request->proxy_config != NULL && *request->proxy_config != '\0')
-    proto = request->proxy_config;
-  else
-    proto = "http";
-
   if (request->username == NULL || *request->username == '\0')
-    tempstr = g_strconcat ("GET ", proto, "://", 
+    tempstr = g_strconcat ("GET ", request->url_prefix, "://", 
                            request->hostname, "/", request->directory, 
                            use_http11 ? "/ HTTP/1.1\n" : "/ HTTP/1.0\n", NULL);
   else
-    tempstr = g_strconcat ("GET ", proto, "://", request->username, "@", 
-                           request->hostname, "/", request->directory, 
+    tempstr = g_strconcat ("GET ", request->url_prefix, "://", 
+                           request->username, "@", request->hostname, "/", 
+                           request->directory, 
                            use_http11 ? "/ HTTP/1.1\n" : "/ HTTP/1.0\n", NULL);
 
   if ((pos = strstr (tempstr, "://")) != NULL)
@@ -431,28 +462,28 @@
 static off_t 
 rfc2068_get_file_size (gftp_request * request, const char *filename)
 {
-  char *tempstr, *pos, *proto;
+  rfc2068_params *params;
+  char *tempstr, *pos;
+  int ret, use_http11;
   off_t size;
-  int ret;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL);
   g_return_val_if_fail (filename != NULL, GFTP_EFATAL);
 
+  params = request->protocol_data;
+  gftp_lookup_request_option (request, "use_http11", &use_http11);
+
   if (request->sockfd < 0 && (ret = rfc2068_connect (request)) != 0)
     return (ret);
 
-  if (request->proxy_config != NULL && *request->proxy_config != '\0')
-    proto = request->proxy_config;
-  else
-    proto = "http";
-
   if (request->username == NULL || *request->username == '\0')
-    tempstr = g_strconcat ("HEAD ", proto, request->hostname, "/", filename, 
+    tempstr = g_strconcat ("HEAD ", request->url_prefix, request->hostname, "/",
+                           filename, 
                            use_http11 ? " HTTP/1.1\n" : " HTTP/1.0\n", NULL);
   else
-    tempstr = g_strconcat ("HEAD ", proto, request->username, "@", 
-                           request->hostname, "/", filename, 
+    tempstr = g_strconcat ("HEAD ", request->url_prefix, request->username, 
+                           "@", request->hostname, "/", filename, 
                            use_http11 ? " HTTP/1.1\n" : " HTTP/1.0\n", NULL);
 
   if ((pos = strstr (tempstr, "://")) != NULL)
@@ -677,14 +708,6 @@
 static void
 rfc2068_set_config_options (gftp_request * request)
 {
-  gftp_set_proxy_hostname (request, http_proxy_host);
-  gftp_set_proxy_port (request, http_proxy_port);
-  gftp_set_proxy_username (request, http_proxy_username);
-  gftp_set_proxy_password (request, http_proxy_password);
-
-
-  if (request->proxy_config == NULL)
-    request->proxy_config = g_strdup ("http");
 }
 
 
@@ -699,6 +722,13 @@
 }
 
 
+void 
+rfc2068_register_module (void)
+{
+  gftp_register_config_vars (config_vars);
+}
+
+
 void
 rfc2068_init (gftp_request * request)
 {
@@ -718,7 +748,6 @@
   request->abort_transfer = rfc2068_end_transfer; /* NOTE: uses end_transfer */
   request->list_files = rfc2068_list_files;
   request->get_next_file = rfc2068_get_next_file;
-  request->set_data_type = NULL;
   request->get_file_size = rfc2068_get_file_size;
   request->chdir = rfc2068_chdir;
   request->rmdir = NULL;
@@ -731,7 +760,6 @@
   request->swap_socks = NULL;
   request->set_config_options = rfc2068_set_config_options;
   request->url_prefix = g_strdup ("http");
-  request->protocol_name = "HTTP";
   request->need_hostport = 1;
   request->need_userpass = 0;
   request->use_cache = 1;
--- a/lib/rfc959.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/rfc959.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  rfc959.c - General purpose routines for the FTP protocol (RFC 959)       */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -20,10 +20,79 @@
 #include "gftp.h"
 static const char cvsid[] = "$Id$";
 
+static gftp_config_vars config_vars[] = 
+{
+  {"", N_("FTP"), gftp_option_type_notebook, NULL, NULL, 0, NULL, 
+   GFTP_PORT_GTK, NULL},
+
+  {"email", N_("Email address:"), 
+   gftp_option_type_text, "", NULL, 0,
+   N_("This is the password that will be used whenever you log into a remote FTP server as anonymous"), 
+   GFTP_PORT_ALL, NULL},
+  {"passive_transfer", N_("Passive file transfers"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 0,
+   N_("If this is enabled, then the remote FTP server will open up a port for the data connection. If you are behind a firewall, you will need to enable this. Generally, it is a good idea to keep this enabled unless you are connecting to an older FTP server that doesn't support this. If this is disabled, then gFTP will open up a port on the client side and the remote server will attempt to connect to it."),
+   GFTP_PORT_ALL, NULL},
+  {"resolve_symlinks", N_("Resolve Remote Symlinks (LIST -L)"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 0,
+   N_("The remote FTP server will attempt to resolve symlinks in the directory listings. Generally, this is a good idea to leave enabled. The only time you will want to disable this is if the remote FTP server doesn't support the -L option to LIST"), 
+   GFTP_PORT_ALL, NULL},
+  {"ascii_transfers", N_("Transfer files in ASCII mode"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, 0,
+   N_("If you are transfering a text file from Windows to UNIX box or vice versa, then you should enable this. Each system represents newlines differently. If you are transfering from UNIX to UNIX, then it is safe to leave this off."), 
+   GFTP_PORT_ALL, NULL},
+  {"ftp_proxy_host", N_("Proxy hostname:"), 
+   gftp_option_type_text, "", NULL, 0,
+   N_("Firewall hostname"), GFTP_PORT_ALL, NULL},
+  {"ftp_proxy_port", N_("Proxy port:"), 
+   gftp_option_type_int, GINT_TO_POINTER(21), NULL, 0,
+   N_("Port to connect to on the firewall"), GFTP_PORT_ALL, NULL},
+  {"ftp_proxy_username", N_("Proxy username:"), 
+   gftp_option_type_text, "", NULL, 0,
+   N_("Your firewall username"), GFTP_PORT_ALL, NULL},
+  {"ftp_proxy_password", N_("Proxy password:"), 
+   gftp_option_type_hidetext, "", NULL, 0,
+   N_("Your firewall password"), GFTP_PORT_ALL, NULL},
+  {"ftp_proxy_account", N_("Proxy account:"), 
+   gftp_option_type_text, "", NULL, 0,
+   N_("Your firewall account (optional)"), GFTP_PORT_ALL, NULL},
+  
+  {"", "", gftp_option_type_newtable, "", NULL, 0, "", GFTP_PORT_GTK, NULL},
+/* FIXME  {"", N_("Proxy server type"), CONFIG_COMBO, "PS", NULL, GFTP_PORT_GTK},*/
+  {"proxy_config", N_("Proxy config"), 
+   gftp_option_type_textbox, "", NULL, 0,
+   N_("This specifies how your proxy server expects us to log in"), 
+   GFTP_PORT_GTK, NULL},
+
+  {"", N_("%pu = proxy user"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%hu = host user"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%pp = proxy pass"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%hp = host pass"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%ph = proxy host"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%hh = host"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%po = proxy port"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%ho = host port"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL}, 
+  {"", N_("%pa = proxy account"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {"", N_("%ha = host account"), gftp_option_type_label, "", NULL, 0, "", 
+   GFTP_PORT_GTK, NULL},
+  {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
+};
+
+         
 typedef struct rfc959_params_tag
 {
   gftp_getline_buffer * sockfd_rbuf,
                       * datafd_rbuf;
+  int is_ascii_transfer;
 } rfc959_parms;
 
 
@@ -114,14 +183,16 @@
 static char *
 parse_ftp_proxy_string (gftp_request * request)
 {
-  char *startpos, *endpos, *oldstr, *newstr, *newval, *tempport;
+  char *startpos, *endpos, *oldstr, *newstr, *newval, *tempport, *proxy_config;
+  int tmp;
 
   g_return_val_if_fail (request != NULL, NULL);
   g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, NULL);
 
   newstr = g_malloc (1);
   *newstr = '\0';
-  startpos = endpos = request->proxy_config;
+  gftp_lookup_request_option (request, "proxy_config", &proxy_config);
+  startpos = endpos = proxy_config;
   while (*endpos != '\0')
     {
       tempport = NULL;
@@ -130,20 +201,21 @@
 	  switch (tolower ((int) *(endpos + 2)))
 	    {
 	    case 'u':
-	      newval = request->proxy_username;
+              gftp_lookup_request_option (request, "firewall_username", &newval);
 	      break;
 	    case 'p':
-	      newval = request->proxy_password;
+              gftp_lookup_request_option (request, "firewall_password", &newval);
 	      break;
 	    case 'h':
-	      newval = request->proxy_hostname;
+              gftp_lookup_request_option (request, "firewall_host", &newval);
 	      break;
 	    case 'o':
-	      tempport = g_strdup_printf ("%d", request->proxy_port);
+              gftp_lookup_request_option (request, "firewall_port", &tmp);
+	      tempport = g_strdup_printf ("%d", tmp);
 	      newval = tempport;
 	      break;
 	    case 'a':
-	      newval = request->proxy_account;
+              gftp_lookup_request_option (request, "firewall_account", &newval);
 	      break;
 	    default:
 	      endpos++;
@@ -317,11 +389,11 @@
 
   *endpos = '\0';
   if (strcmp (stpos, "UNIX") == 0)
-    request->server_type = GFTP_TYPE_UNIX;
+    request->server_type = GFTP_DIRTYPE_UNIX;
   else if (strcmp (stpos, "VMS") == 0)
-    request->server_type = GFTP_TYPE_VMS;
+    request->server_type = GFTP_DIRTYPE_VMS;
   else
-    request->server_type = GFTP_TYPE_OTHER;
+    request->server_type = GFTP_DIRTYPE_OTHER;
 
   return (0);
 }
@@ -330,8 +402,9 @@
 static int
 rfc959_connect (gftp_request * request)
 {
-  char tempchar, *startpos, *endpos, *tempstr;
-  int ret, resp;
+  char tempchar, *startpos, *endpos, *tempstr, *email, *proxy_hostname;
+  int ret, resp, ascii_transfers, proxy_port;
+  rfc959_parms * parms;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, GFTP_EFATAL);
@@ -340,15 +413,22 @@
   if (request->sockfd > 0)
     return (0);
 
+  parms = request->protocol_data;
+
+  gftp_lookup_request_option (request, "email", &email);
+  gftp_lookup_request_option (request, "firewall_host", &proxy_hostname);
+  gftp_lookup_request_option (request, "firewall_port", &proxy_port);
+
   if (request->username == NULL || *request->username == '\0')
     {
       gftp_set_username (request, "anonymous");
-      gftp_set_password (request, emailaddr);
+      gftp_set_password (request, email);
     }
   else if (strcasecmp (request->username, "anonymous") == 0)
-    gftp_set_password (request, emailaddr);
-    
-  if ((request->sockfd = gftp_connect_server (request, "ftp")) < 0)
+    gftp_set_password (request, email);
+   
+  if ((request->sockfd = gftp_connect_server (request, "ftp", proxy_hostname,
+                                              proxy_port)) < 0)
     return (request->sockfd);
 
   /* Get the banner */
@@ -416,10 +496,17 @@
   if ((ret = rfc959_syst (request)) < 0 && request->sockfd < 0)
     return (ret);
 
-  if (request->data_type == GFTP_TYPE_BINARY)
-    tempstr = "TYPE I\r\n";
+  gftp_lookup_request_option (request, "ascii_transfers", &ascii_transfers);
+  if (ascii_transfers)
+    {
+      tempstr = "TYPE A\r\n";
+      parms->is_ascii_transfer = 1;
+    }
   else
-    tempstr = "TYPE A\r\n";
+    {
+      tempstr = "TYPE I\r\n";
+      parms->is_ascii_transfer = 0;
+    }
 
   if ((ret = rfc959_send_command (request, tempstr)) < 0)
     return (ret);
@@ -472,10 +559,10 @@
 {
   char *pos, *pos1, resp, *command;
   struct sockaddr_in data_addr;
+  int i, passive_transfer;
   size_t data_addr_len;
   unsigned int temp[6];
   unsigned char ad[6];
-  int i;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, GFTP_EFATAL);
@@ -494,14 +581,15 @@
   memset (&data_addr, 0, data_addr_len);
   data_addr.sin_family = AF_INET;
 
-  if (request->transfer_type == gftp_transfer_passive)
+  gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
+  if (passive_transfer)
     {
       if ((resp = rfc959_send_command (request, "PASV\r\n")) != '2')
 	{
           if (request->sockfd < 0)
             return (resp);
 
-	  request->transfer_type = gftp_transfer_active;
+          gftp_set_request_option (request, "passive_transfer", GINT_TO_POINTER(0));
 	  return (rfc959_data_connection_new (request));
 	}
 
@@ -608,14 +696,16 @@
 static int
 rfc959_accept_active_connection (gftp_request * request)
 {
+  int infd, ret, passive_transfer;
   struct sockaddr_in cli_addr;
   size_t cli_addr_len;
-  int infd, ret;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, GFTP_EFATAL);
   g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
-  g_return_val_if_fail (request->transfer_type == gftp_transfer_active, GFTP_EFATAL);
+
+  gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
+  g_return_val_if_fail (!passive_transfer, GFTP_EFATAL);
 
   cli_addr_len = sizeof (cli_addr);
 
@@ -642,12 +732,74 @@
 }
 
 
+static int
+rfc959_is_ascii_transfer (const char *filename)
+{
+  gftp_config_list_vars * tmplistvar;
+  gftp_file_extensions * tempext;
+  GList * templist;
+  int stlen, ret;
+  
+  gftp_lookup_global_option ("ext", &tmplistvar);
+
+  ret = 0; 
+  stlen = strlen (filename);
+  for (templist = tmplistvar->list; templist != NULL; templist = templist->next)
+    {
+      tempext = templist->data;
+
+      if (stlen >= tempext->stlen &&
+          strcmp (&filename[stlen - tempext->stlen], tempext->ext) == 0)
+        {
+          if (toupper (*tempext->ascii_binary == 'A'))
+            ret = 1; 
+          break;
+        }
+    }
+
+  return (ret);
+}
+
+
+static void
+rfc959_set_data_type (gftp_request * request, const char *filename)
+{
+  rfc959_parms * parms;
+  int new_ascii;
+  char *tempstr;
+
+  g_return_if_fail (request != NULL);
+  g_return_if_fail (request->protonum == GFTP_FTP_NUM);
+
+  parms = request->protocol_data;
+  new_ascii = rfc959_is_ascii_transfer (filename);
+
+  if (request->sockfd > 0 && new_ascii != parms->is_ascii_transfer)
+    {
+      if (new_ascii)
+        {
+	  tempstr = "TYPE A\r\n";
+          parms->is_ascii_transfer = 1;
+        }
+      else
+        {
+	  tempstr = "TYPE I\r\n";
+          parms->is_ascii_transfer = 1;
+        }
+
+      rfc959_send_command (request, tempstr);
+    }
+
+  return;
+}
+
+
 static off_t
 rfc959_get_file (gftp_request * request, const char *filename, int fd,
                  off_t startsize)
 {
   char *command, *tempstr, resp;
-  int ret;
+  int ret, passive_transfer;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, GFTP_EFATAL);
@@ -657,6 +809,8 @@
   if (fd > 0)
     request->datafd = fd;
 
+  rfc959_set_data_type (request, filename);
+
   if (request->datafd < 0 && 
       (ret = rfc959_data_connection_new (request)) < 0)
     return (ret);
@@ -693,7 +847,8 @@
       return (GFTP_ERETRYABLE);
     }
 
-  if (request->transfer_type == gftp_transfer_active &&
+  gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
+  if (!passive_transfer &&
       (ret = rfc959_accept_active_connection (request)) < 0)
     return (ret);
 
@@ -715,7 +870,7 @@
                  off_t startsize, off_t totalsize)
 {
   char *command, *tempstr, resp;
-  int ret;
+  int ret, passive_transfer;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, GFTP_EFATAL);
@@ -725,6 +880,8 @@
   if (fd > 0)
     fd = request->datafd;
 
+  rfc959_set_data_type (request, filename);
+
   if (request->datafd < 0 && 
       (ret = rfc959_data_connection_new (request)) < 0)
     return (ret);
@@ -759,7 +916,8 @@
       return (GFTP_ERETRYABLE);
     }
 
-  if (request->transfer_type == gftp_transfer_active && 
+  gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
+  if (!passive_transfer &&
       (ret = rfc959_accept_active_connection (request)) < 0)
     return (ret);
 
@@ -782,8 +940,8 @@
   g_return_val_if_fail (fromreq->sockfd > 0, GFTP_EFATAL);
   g_return_val_if_fail (toreq->sockfd > 0, GFTP_EFATAL);
 
-  fromreq->transfer_type = gftp_transfer_passive;
-  toreq->transfer_type = gftp_transfer_active;
+  gftp_set_request_option (fromreq, "passive_transfer", GINT_TO_POINTER(1));
+  gftp_set_request_option (toreq, "passive_transfer", GINT_TO_POINTER(0));
 
   if ((ret = rfc959_send_command (fromreq, "PASV\r\n")) != '2')
     return (ret);
@@ -894,8 +1052,8 @@
 static int
 rfc959_list_files (gftp_request * request)
 {
+  int ret, show_hidden_files, resolve_symlinks, passive_transfer;
   char *tempstr, parms[3];
-  int ret;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, GFTP_EFATAL);
@@ -904,6 +1062,10 @@
   if ((ret = rfc959_data_connection_new (request)) < 0)
     return (ret);
 
+  gftp_lookup_request_option (request, "show_hidden_files", &show_hidden_files);
+  gftp_lookup_request_option (request, "resolve_symlinks", &resolve_symlinks);
+  gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
+
   *parms = '\0';
   strcat (parms, show_hidden_files ? "a" : "");
   strcat (parms, resolve_symlinks ? "L" : "");
@@ -917,13 +1079,90 @@
     return (GFTP_ERETRYABLE);
 
   ret = 0;
-  if (request->transfer_type == gftp_transfer_active)
+  if (!passive_transfer)
     ret = rfc959_accept_active_connection (request);
 
   return (ret);
 }
 
 
+static ssize_t
+rfc959_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
+{
+  int i, j, ascii_transfers;
+  ssize_t num_read;
+
+  num_read = gftp_read (request, buf, size, request->datafd);
+  if (num_read < 0)
+    return (num_read);
+
+  gftp_lookup_request_option (request, "ascii_transfers", &ascii_transfers);
+  if (ascii_transfers)
+    {
+      for (i = 0, j = 0; i < num_read; i++)
+        {
+          if (buf[i] != '\r')
+            buf[j++] = buf[i];
+          else
+            num_read--;
+        }
+    }
+
+  return (num_read);
+}
+
+
+static ssize_t
+rfc959_put_next_file_chunk (gftp_request * request, char *buf, size_t size)
+{
+  int i, j, ascii_transfers;
+  ssize_t num_wrote;
+  char *tempstr;
+  size_t rsize;
+
+  if (size == 0)
+    return (0);
+
+  gftp_lookup_request_option (request, "ascii_transfers", &ascii_transfers);
+  if (ascii_transfers)
+    {
+      rsize = 0;
+      for (i = 0; i < size; i++)
+        {
+          rsize++;
+          if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
+            rsize++;
+        }
+
+      if (rsize != size)
+        {
+          tempstr = g_malloc (rsize);
+
+          for (i = 0, j = 0; i < size; i++)
+            {
+              if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
+                tempstr[j++] = '\r';
+              tempstr[j++] = buf[i];
+            }
+        }
+      else
+        tempstr = buf;
+    }
+  else
+    {
+      rsize = size;
+      tempstr = buf;
+    }
+
+  num_wrote = gftp_write (request, tempstr, rsize, request->datafd);
+
+  if (tempstr != buf)
+    g_free (tempstr);
+
+  return (num_wrote);
+}
+
+
 int
 rfc959_get_next_file (gftp_request * request, gftp_file * fle, int fd)
 {
@@ -978,30 +1217,6 @@
 }
 
 
-static int
-rfc959_set_data_type (gftp_request * request, int data_type)
-{
-  char *tempstr;
-  int ret;
-
-  g_return_val_if_fail (request != NULL, GFTP_EFATAL);
-  g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, GFTP_EFATAL);
-
-  if (request->sockfd > 0 && request->data_type != data_type)
-    {
-      if (data_type == GFTP_TYPE_BINARY)
-	tempstr = "TYPE I\r\n";
-      else
-	tempstr = "TYPE A\r\n";
-
-      if ((ret = rfc959_send_command (request, tempstr)) != '2')
-	return (ret);
-    }
-  request->data_type = data_type;
-  return (0);
-}
-
-
 static off_t
 rfc959_get_file_size (gftp_request * request, const char *filename)
 {
@@ -1178,30 +1393,40 @@
 static void
 rfc959_set_config_options (gftp_request * request)
 {
-  request->transfer_type = passive_transfer ? gftp_transfer_passive : gftp_transfer_active;
+  char *proxy_config;
 
-  if (strcmp (proxy_config, "http") != 0)
+  gftp_lookup_request_option (request, "proxy_config", &proxy_config);
+  if (strcmp (proxy_config, "http") == 0)
     {
-      gftp_set_proxy_hostname (request, firewall_host);
-      gftp_set_proxy_port (request, firewall_port);
-      gftp_set_proxy_username (request, firewall_username);
-      gftp_set_proxy_password (request, firewall_password);
-      gftp_set_proxy_account (request, firewall_account);
-      gftp_set_proxy_config (request, proxy_config);
+      gftp_protocols[GFTP_HTTP_NUM].init (request);
+      gftp_set_request_option (request, "proxy_config", "ftp");
     }
-  else
-    {
-      gftp_set_proxy_hostname (request, http_proxy_host);
-      gftp_set_proxy_port (request, http_proxy_port);
-      gftp_set_proxy_username (request, http_proxy_username);
-      gftp_set_proxy_password (request, http_proxy_password);
+}
 
 
-      if (request->proxy_config == NULL)
-        {
-          gftp_protocols[GFTP_HTTP_NUM].init (request);
-          request->proxy_config = g_strdup ("ftp");
-        }
+void 
+rfc959_register_module (void)
+{
+  struct hostent *hent;
+  struct utsname unme;
+  struct passwd *pw;
+  char *tempstr;
+
+  gftp_register_config_vars (config_vars);
+
+  gftp_lookup_global_option ("email", &tempstr);
+  if (tempstr == NULL || *tempstr == '\0')
+    {
+      /* If there is no email address specified, then we'll just use the
+         currentuser@currenthost */
+      uname (&unme);
+      pw = getpwuid (geteuid ());
+      hent = gethostbyname (unme.nodename);
+      if (strchr (unme.nodename, '.') == NULL && hent != NULL)
+        tempstr = g_strconcat (pw->pw_name, "@", hent->h_name, NULL);
+      else
+        tempstr = g_strconcat (pw->pw_name, "@", unme.nodename, NULL);
+      gftp_set_global_option ("email", tempstr);
     }
 }
 
@@ -1219,13 +1444,12 @@
   request->get_file = rfc959_get_file;
   request->put_file = rfc959_put_file;
   request->transfer_file = rfc959_transfer_file;
-  request->get_next_file_chunk = NULL;
-  request->put_next_file_chunk = NULL;
+  request->get_next_file_chunk = rfc959_get_next_file_chunk;
+  request->put_next_file_chunk = rfc959_put_next_file_chunk;
   request->end_transfer = rfc959_end_transfer;
   request->abort_transfer = rfc959_abort_transfer;
   request->list_files = rfc959_list_files;
   request->get_next_file = rfc959_get_next_file;
-  request->set_data_type = rfc959_set_data_type;
   request->get_file_size = rfc959_get_file_size;
   request->chdir = rfc959_chdir;
   request->rmdir = rfc959_rmdir;
@@ -1239,7 +1463,6 @@
   request->swap_socks = NULL;
   request->set_config_options = rfc959_set_config_options;
   request->url_prefix = "ftp";
-  request->protocol_name = "FTP";
   request->need_hostport = 1;
   request->need_userpass = 1;
   request->use_cache = 1;
--- a/lib/sshv2.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/lib/sshv2.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  sshv2.c - functions that will use the sshv2 protocol                     */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -23,6 +23,36 @@
 #define SSH_MAX_HANDLE_SIZE		256
 #define SSH_MAX_STRING_SIZE		34000
 
+static gftp_config_vars config_vars[] =
+{
+  {"", N_("SSH"), gftp_option_type_notebook, NULL, NULL, 0, NULL, 
+   GFTP_PORT_GTK, NULL},
+
+  {"ssh_prog_name", N_("SSH Prog Name:"), 
+   gftp_option_type_text, "ssh", NULL, 0,
+   N_("The path to the SSH executable"), GFTP_PORT_ALL, NULL},
+  {"ssh_extra_params", N_("SSH Extra Params:"), 
+   gftp_option_type_textarray, NULL, NULL, 0,  
+   N_("Extra parameters to pass to the SSH program"), GFTP_PORT_ALL, NULL},
+  {"ssh2_sftp_path", N_("SSH2 sftp-server path:"), 
+   gftp_option_type_text, NULL, NULL, 0,
+   N_("Default remote SSH2 sftp-server path"), GFTP_PORT_ALL, NULL},
+
+  {"ssh_need_userpass", N_("Need SSH User/Pass"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, 0,
+   N_("Require a username/password for SSH connections"), GFTP_PORT_ALL, NULL},
+  {"ssh_use_askpass", N_("Use ssh-askpass utility"),
+   gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, 0,
+   N_("Use the ssh-askpass utility to supply the remote password"), GFTP_PORT_GTK,
+   NULL},
+  {"sshv2_use_sftp_subsys", N_("Use SSH2 SFTP subsys"), 
+   gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, 0,
+   N_("Call ssh with the -s sftp flag. This is helpful because you won't have to know the remote path to the remote sftp-server"), 
+   GFTP_PORT_GTK, NULL},
+  {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
+};
+
+
 typedef struct sshv2_attribs_tag
 {
   gint32 flags;
@@ -112,6 +142,254 @@
 #define SSH_FX_CONNECTION_LOST               7
 #define SSH_FX_OP_UNSUPPORTED                8
 
+#define SSH_LOGIN_BUFSIZE	200
+#define SSH_ERROR_BADPASS	-1
+#define SSH_ERROR_QUESTION	-2
+#define SSH_WARNING 		-3
+
+/* We have the caller send us a pointer to a string so we can write the port
+   into it. It makes it easier so we don't have to worry about freeing it 
+   later on, the caller can just send us an auto variable, The string
+   should be at least 6 chars. I know this is messy... */
+
+static char **
+sshv2_gen_exec_args (gftp_request * request, char *execname, 
+                    int use_sftp_subsys, char *portstring)
+{
+  char **args, *oldstr, *tempstr, *ssh_prog_name, **ssh_extra_params_list;
+  int i, j, num_ssh_extra_params;
+  struct servent serv_struct;
+
+  ssh_extra_params_list = NULL;
+  gftp_lookup_request_option (request, "ssh_extra_params", 
+                              &ssh_extra_params_list);
+
+  num_ssh_extra_params = 0;
+  if (ssh_extra_params_list != NULL)
+    {
+      for (j=0; ssh_extra_params_list[j] != NULL; j++)
+        {
+          num_ssh_extra_params++;
+        }
+     }
+
+  args = g_malloc (sizeof (char *) * (num_ssh_extra_params + 15));
+
+  ssh_prog_name = "ssh";
+  gftp_lookup_request_option (request, "ssh_prog_name", &ssh_prog_name);
+  args[0] = ssh_prog_name;
+
+  i = 1;
+  tempstr = g_strdup (args[0]);
+
+
+  if (ssh_extra_params_list != NULL)
+    {
+      for (j=0; ssh_extra_params_list[j] != NULL; j++)
+        {
+          oldstr = tempstr;
+          args[i++] = ssh_extra_params_list[j];
+          tempstr = g_strconcat (oldstr, " ", ssh_extra_params_list[j], NULL);
+          g_free (oldstr);
+        }
+    }
+
+  oldstr = tempstr;
+  tempstr = g_strconcat (oldstr, " -e none", NULL);
+  g_free (oldstr);
+  args[i++] = "-e";
+  args[i++] = "none";
+
+  if (request->username && *request->username != '\0')
+    {
+      oldstr = tempstr;
+      tempstr = g_strconcat (oldstr, " -l ", request->username, NULL);
+      g_free (oldstr);
+      args[i++] = "-l";
+      args[i++] = request->username;
+    }
+
+  if (request->port != 0)
+    {
+      g_snprintf (portstring, 6, "%d", request->port);
+      oldstr = tempstr;
+      tempstr = g_strconcat (oldstr, " -p ", portstring, NULL);
+      g_free (oldstr);
+      args[i++] = "-p";
+      args[i++] = portstring;
+    }
+  else
+    {
+      if (!r_getservbyname ("ssh", "tcp", &serv_struct, NULL))
+        request->port = 22;
+      else
+        request->port = ntohs (serv_struct.s_port);
+    }
+
+  if (use_sftp_subsys)
+    {
+      oldstr = tempstr;
+      tempstr = g_strconcat (oldstr, " ", request->hostname, " -s sftp", NULL);
+      g_free (oldstr);
+      args[i++] = request->hostname;
+      args[i++] = "-s";
+      args[i++] = "sftp";
+      args[i] = NULL;
+    }
+  else
+    {
+      oldstr = tempstr;
+      tempstr = g_strconcat (oldstr, " ", request->hostname, " \"", execname, 
+                             "\"", NULL);
+      g_free (oldstr);
+      args[i++] = request->hostname;
+      args[i++] = execname;
+      args[i] = NULL;
+    }
+
+  request->logging_function (gftp_logging_misc, request->user_data, 
+                             _("Running program %s\n"), tempstr);
+  g_free (tempstr);
+  return (args);
+}
+
+
+static char *
+sshv2_start_login_sequence (gftp_request * request, int fd)
+{
+  char *tempstr, *pwstr, *tmppos;
+  size_t rem, len, diff, lastdiff, key_pos;
+  int wrotepw, ok;
+  ssize_t rd;
+
+  rem = len = SSH_LOGIN_BUFSIZE;
+  tempstr = g_malloc0 (len + 1);
+  key_pos = diff = lastdiff = 0;
+  wrotepw = 0;
+  ok = 1;
+
+  if (gftp_set_sockblocking (request, fd, 1) == -1)
+    return (NULL);
+
+  pwstr = g_strconcat (request->password, "\n", NULL);
+
+  errno = 0;
+  while (1)
+    {
+      if ((rd = gftp_read (request, tempstr + diff, rem - 1, fd)) <= 0)
+        {
+          ok = 0;
+          break;
+        }
+      rem -= rd;
+      diff += rd;
+      tempstr[diff] = '\0'; 
+
+      if (diff > 11 && strcmp (tempstr + diff - 10, "password: ") == 0)
+        {
+          if (wrotepw)
+            {
+              ok = SSH_ERROR_BADPASS;
+              break;
+            }
+
+          if (strstr (tempstr, "WARNING") != NULL ||
+              strstr (tempstr, _("WARNING")) != NULL)
+            {
+              ok = SSH_WARNING;
+              break;
+            }
+              
+          wrotepw = 1;
+          if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0)
+            {
+              ok = 0;
+              break;
+            }
+        }
+      else if (diff > 2 && strcmp (tempstr + diff - 2, ": ") == 0 &&
+               ((tmppos = strstr (tempstr + key_pos, "Enter passphrase for RSA key")) != NULL ||
+                ((tmppos = strstr (tempstr + key_pos, "Enter passphrase for key '")) != NULL)))
+        {
+          key_pos = diff;
+          if (wrotepw)
+            {
+              ok = SSH_ERROR_BADPASS;
+              break;
+            }
+
+          if (strstr (tempstr, "WARNING") != NULL ||
+              strstr (tempstr, _("WARNING")) != NULL)
+            {
+              ok = SSH_WARNING;
+              break;
+            }
+
+          wrotepw = 1;
+          if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0)
+            {
+              ok = 0;
+              break;
+            }
+        }
+      else if (diff > 10 && strcmp (tempstr + diff - 10, "(yes/no)? ") == 0)
+        {
+          ok = SSH_ERROR_QUESTION;
+          break;
+        }
+      else if (diff >= 5 && strcmp (tempstr + diff - 5, "xsftp") == 0)
+        break;
+      else if (rem <= 1)
+        {
+          request->logging_function (gftp_logging_recv, request->user_data,
+                                     "%s", tempstr + lastdiff);
+          len += SSH_LOGIN_BUFSIZE;
+          rem += SSH_LOGIN_BUFSIZE;
+          lastdiff = diff;
+          tempstr = g_realloc (tempstr, len);
+          continue;
+        }
+    }
+
+  g_free (pwstr);
+
+  if (*(tempstr + lastdiff) != '\0')
+    request->logging_function (gftp_logging_recv, request->user_data,
+                               "%s\n", tempstr + lastdiff);
+
+  if (ok <= 0)
+    {
+      if (ok == SSH_ERROR_BADPASS)
+        request->logging_function (gftp_logging_error, request->user_data,
+                               _("Error: An incorrect password was entered\n"));
+      else if (ok == SSH_ERROR_QUESTION)
+        request->logging_function (gftp_logging_error, request->user_data,
+                               _("Please connect to this host with the command line SSH utility and answer this question appropriately.\n"));
+      else if (ok == SSH_WARNING)
+        request->logging_function (gftp_logging_error, request->user_data,
+                                   _("Please correct the above warning to connect to this host.\n"));
+
+      g_free (tempstr);
+      return (NULL);
+    }
+ 
+  return (tempstr);
+}
+
+
+#ifdef G_HAVE_GINT64
+
+static gint64
+hton64 (gint64 val)
+{
+  if (G_BYTE_ORDER != G_BIG_ENDIAN)
+    return (GINT64_TO_BE (val));
+  else
+    return (val);
+}
+
+#endif
+
 
 static void
 sshv2_log_command (gftp_request * request, gftp_logging_level level,
@@ -523,8 +801,9 @@
 static int
 sshv2_connect (gftp_request * request)
 {
-  char **args, *tempstr, pts_name[20], *p1, p2, *exepath, port[6];
-  int version, fdm, fds, s[2], ret;
+  int version, fdm, fds, s[2], ret, ssh_use_askpass, sshv2_use_sftp_subsys;
+  char **args, *tempstr, pts_name[20], *p1, p2, *exepath, port[6],
+       *ssh2_sftp_path;
   sshv2_message message;
   pid_t child;
 
@@ -544,21 +823,25 @@
      any initial text from the server, and we'll block. So I just send a 
      xsftp server banner over. I hope this works on most Unices */
 
-  if (request->sftpserv_path == NULL ||
-      *request->sftpserv_path == '\0')
+  gftp_lookup_request_option (request, "ssh2_sftp_path", &ssh2_sftp_path);
+  gftp_lookup_request_option (request, "ssh_use_askpass", &ssh_use_askpass);
+  gftp_lookup_request_option (request, "sshv2_use_sftp_subsys", 
+                              &sshv2_use_sftp_subsys);
+
+  if (ssh2_sftp_path == NULL || *ssh2_sftp_path == '\0')
     {
       p1 = "";
       p2 = ' ';
     }
   else
     {
-      p1 = request->sftpserv_path;
+      p1 = ssh2_sftp_path;
       p2 = '/';
     }
 
   *port = '\0';
   exepath = g_strdup_printf ("echo -n xsftp ; %s%csftp-server", p1, p2);
-  args = make_ssh_exec_args (request, exepath, sshv2_use_sftp_subsys, port);
+  args = sshv2_gen_exec_args (request, exepath, sshv2_use_sftp_subsys, port);
 
   if (ssh_use_askpass || sshv2_use_sftp_subsys)
     {
@@ -608,8 +891,7 @@
       dup2 (fds, 2);
       if (!ssh_use_askpass && fds > 2)
         close (fds);
-      execvp (ssh_prog_name != NULL && *ssh_prog_name != '\0' ?
-              ssh_prog_name : "ssh", args);
+      execvp (args[0], args);
 
       printf (_("Error: Cannot execute ssh: %s\n"), g_strerror (errno));
       exit (1);
@@ -624,7 +906,7 @@
       tty_raw (fdm);
       if (!sshv2_use_sftp_subsys)
         {
-          tempstr = ssh_start_login_sequence (request, fdm);
+          tempstr = sshv2_start_login_sequence (request, fdm);
           if (!tempstr ||
               !(strlen (tempstr) > 4 && strcmp (tempstr + strlen (tempstr) - 5,
                                                 "xsftp") == 0))
@@ -1941,19 +2223,9 @@
 static void
 sshv2_set_config_options (gftp_request * request)
 {
-  if (request->sftpserv_path != NULL)
-    {
-      if (ssh2_sftp_path != NULL && 
-          strcmp (ssh2_sftp_path, request->sftpserv_path) == 0)
-        return;
+  int ssh_need_userpass;
 
-      g_free (request->sftpserv_path);
-      request->sftpserv_path = NULL;
-    }
-
-  if (ssh2_sftp_path != NULL)
-    request->sftpserv_path = g_strdup (ssh2_sftp_path);
-
+  gftp_lookup_request_option (request, "ssh_need_userpass", &ssh_need_userpass);
   request->need_userpass = ssh_need_userpass;
 }
 
@@ -1969,6 +2241,13 @@
 }
 
 
+void 
+sshv2_register_module (void)
+{
+  gftp_register_config_vars (config_vars);
+}
+
+
 void
 sshv2_init (gftp_request * request)
 {
@@ -1990,7 +2269,6 @@
   request->abort_transfer = sshv2_end_transfer; /* NOTE: uses sshv2_end_transfer */
   request->list_files = sshv2_list_files;
   request->get_next_file = sshv2_get_next_file;
-  request->set_data_type = NULL;
   request->get_file_size = sshv2_get_file_size;
   request->chdir = sshv2_chdir;
   request->rmdir = sshv2_rmdir;
@@ -2004,14 +2282,13 @@
   request->set_config_options = sshv2_set_config_options;
   request->swap_socks = sshv2_swap_socks;
   request->url_prefix = "ssh2";
-  request->protocol_name = "SSH2";
   request->need_hostport = 1;
-  request->need_userpass = ssh_need_userpass;
+  request->need_userpass = 1;
   request->use_cache = 1;
   request->use_threads = 1;
   request->always_connected = 0;
   request->protocol_data = g_malloc0 (sizeof (sshv2_params));
-  request->server_type = GFTP_TYPE_UNIX;
+  request->server_type = GFTP_DIRTYPE_UNIX;
   gftp_set_config_options (request);
 
   params = request->protocol_data;
--- a/src/text/gftp-text.c	Sat Apr 05 02:25:42 2003 +0000
+++ b/src/text/gftp-text.c	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  gftp-text.c - text port of gftp                                          */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -94,9 +94,9 @@
 int
 main (int argc, char **argv)
 {
+  char *pos, *stpos, *startup_directory;
   gftp_request * request;
   size_t len, cmdlen;
-  char *pos, *stpos;
   int i;
 #ifdef HAVE_LIBREADLINE
   char *tempstr, prompt[20];
@@ -117,22 +117,34 @@
 
   /* SSH doesn't support reading the password with askpass via the command 
      line */
-  ssh_use_askpass = sshv2_use_sftp_subsys = 0;
 
   if (gftp_parse_command_line (&argc, &argv) != 0)
     exit (0);
 
   gftp_text_remreq = gftp_request_new ();
+  gftp_set_request_option (gftp_text_remreq, "ssh_use_askpass", 
+                           GINT_TO_POINTER(0));
+  gftp_set_request_option (gftp_text_remreq, "ssh_use_sftp_subsys", 
+                           GINT_TO_POINTER(0));
   gftp_text_remreq->logging_function = gftp_text_log;
 
   gftp_text_locreq = gftp_request_new ();
+  gftp_set_request_option (gftp_text_locreq, "ssh_use_askpass", 
+                           GINT_TO_POINTER(0));
+  gftp_set_request_option (gftp_text_locreq, "ssh_use_sftp_subsys", 
+                           GINT_TO_POINTER(0));
   gftp_text_locreq->logging_function = gftp_text_log;
   gftp_protocols[GFTP_LOCAL_NUM].init (gftp_text_locreq);
-  if (startup_directory != NULL && *startup_directory != '\0')
+
+  startup_directory = "";
+  gftp_lookup_request_option (gftp_text_locreq, "startup_directory", 
+                              &startup_directory);
+  if (*startup_directory != '\0')
     gftp_set_directory (gftp_text_locreq, startup_directory);
+
   gftp_connect (gftp_text_locreq);
 
-  gftp_text_log (gftp_logging_misc, NULL, "%s, Copyright (C) 1998-2002 Brian Masney <", version);
+  gftp_text_log (gftp_logging_misc, NULL, "%s, Copyright (C) 1998-2003 Brian Masney <", gftp_version);
   gftp_text_log (gftp_logging_recv, NULL, "masneyb@gftp.org");
   gftp_text_log (gftp_logging_misc, NULL, _(">.\nIf you have any questions, comments, or suggestions about this program, please feel free to email them to me. You can always find out the latest news about gFTP from my website at http://www.gftp.org/\n"));
   gftp_text_log (gftp_logging_misc, NULL, "\n");
@@ -226,8 +238,8 @@
 #endif
     }
  
-  if (logfd != NULL)
-    fclose (logfd);
+  if (gftp_logfd != NULL)
+    fclose (gftp_logfd);
   gftp_text_quit (NULL, NULL, NULL);
 
   return (0);
@@ -263,16 +275,16 @@
   g_vsnprintf (tempstr, sizeof (tempstr), string, argp);
   va_end (argp);
 
-  if (logfd != NULL)
+  if (gftp_logfd != NULL)
     {
-      fwrite (tempstr, 1, strlen (tempstr), logfd);
-      if (ferror (logfd))
+      fwrite (tempstr, 1, strlen (tempstr), gftp_logfd);
+      if (ferror (gftp_logfd))
         {
-          fclose (logfd);
-          logfd = NULL;
+          fclose (gftp_logfd);
+          gftp_logfd = NULL;
         }
       else
-        fflush (logfd);
+        fflush (gftp_logfd);
     }
 
   sw = gftp_text_get_win_size ();
@@ -323,7 +335,7 @@
       return (1);
     }
 
-  if (GFTP_GET_USERNAME (request) == NULL)
+  if (request->username == NULL)
     {
       if ((pos = gftp_text_ask_question ("Username [anonymous]", 1, tempstr, 
                                          sizeof (tempstr))) != NULL)
@@ -339,7 +351,7 @@
         gftp_set_username (request, "anonymous");
     }
 
-  if (strcmp (GFTP_GET_USERNAME (request), "anonymous") != 0 && 
+  if (strcmp (request->username, "anonymous") != 0 && 
       (request->password == NULL || *request->password == '\0'))
     {
       if ((pos = gftp_text_ask_question ("Password", 0, tempstr, 
@@ -367,7 +379,8 @@
   char *str;
 
   gftp_text_log (gftp_logging_misc, NULL,
-      "%s. Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>\n", version);
+      "%s. Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>\n", 
+      gftp_version);
 
   str = _("Translated by");
   if (strcmp (str, "Translated by") != 0)
@@ -595,13 +608,13 @@
 
   if (request == gftp_text_locreq)
     {
-      sortcol = local_sortcol;
-      sortasds = local_sortasds;
+      gftp_lookup_request_option (request, "local_sortcol", &sortcol);
+      gftp_lookup_request_option (request, "local_sortasds", &sortasds);
     }
   else
     {
-      sortcol = remote_sortcol;
-      sortasds = remote_sortasds;
+      gftp_lookup_request_option (request, "remote_sortcol", &sortcol);
+      gftp_lookup_request_option (request, "remote_sortasds", &sortasds);
     }
 
   files = gftp_sort_filelist (files, sortcol, sortasds);
@@ -669,8 +682,10 @@
       return (1);
     }
 
-  gftp_set_data_type (gftp_text_remreq, GFTP_TYPE_BINARY);
-  gftp_set_data_type (gftp_text_locreq, GFTP_TYPE_BINARY);
+  gftp_set_request_option (gftp_text_remreq, "ascii_transfers", 
+                           GINT_TO_POINTER(0));
+  gftp_set_request_option (gftp_text_locreq, "ascii_transfers", 
+                           GINT_TO_POINTER(0));
   return (1);
 }
 
@@ -685,8 +700,10 @@
       return (1);
     }
 
-  gftp_set_data_type (gftp_text_remreq, GFTP_TYPE_ASCII);
-  gftp_set_data_type (gftp_text_locreq, GFTP_TYPE_ASCII);
+  gftp_set_request_option (gftp_text_remreq, "ascii_transfers", 
+                           GINT_TO_POINTER(1));
+  gftp_set_request_option (gftp_text_locreq, "ascii_transfers", 
+                           GINT_TO_POINTER(1));
   return (1);
 }
 
@@ -839,7 +856,7 @@
 int
 gftp_text_transfer_files (gftp_transfer * transfer)
 {
-  char *tempstr, buf[8192], *progress = "|/-\\";
+  char buf[8192], *progress = "|/-\\";
   struct timeval updatetime;
   long fromsize, total;
   gftp_file * curfle;
@@ -860,13 +877,6 @@
           continue;
         }
 
-      if (maxkbs > 0)
-       {
-          gftp_text_log (gftp_logging_misc, NULL, 
-                         _("File transfer will be throttled to %.2f KB/s\n"), 
-                         maxkbs);
-        }
-
       transfer->curtrans = curfle->startsize;
       fromsize = gftp_transfer_file (transfer->fromreq, curfle->file, -1,
                                      curfle->startsize, transfer->toreq, curfle->destfile, 
@@ -881,6 +891,7 @@
   
       total = 0;
       i = 0;
+      num_read = -1;
       while (!cancel && (num_read = gftp_get_next_file_chunk (transfer->fromreq,
                                                         buf, sizeof (buf))) > 0)
         {
@@ -890,7 +901,7 @@
             i = 0;
 
           total += num_read;
-          gftp_text_calc_kbs (transfer, num_read);
+          gftp_calc_kbs (transfer, num_read);
           if (transfer->lasttime.tv_sec - updatetime.tv_sec >= 1 || total >= fromsize)
             {
               sw = gftp_text_get_win_size () - 20;
@@ -908,22 +919,11 @@
               memcpy (&updatetime, &transfer->lasttime, sizeof (updatetime));
             }
 
-          if (GFTP_GET_DATA_TYPE (transfer->fromreq) == GFTP_TYPE_ASCII)
-            tempstr = gftp_convert_ascii (buf, &num_read, 1);
-          else
-            tempstr = buf;
-
-          if (gftp_put_next_file_chunk (transfer->toreq, tempstr, num_read) < 0)
+          if (gftp_put_next_file_chunk (transfer->toreq, buf, num_read) < 0)
             {
               num_read = -1;
               break;
             }
-
-          /* We don't have to free tempstr for a download because new memory is
-             not allocated for it in that case */
-          if (GFTP_GET_DATA_TYPE (transfer->fromreq) == 
-              GFTP_TYPE_ASCII && !transfer->transfer_direction)
-            g_free (tempstr);
         }
       printf ("\n");
 
@@ -1014,31 +1014,31 @@
 int
 gftp_text_set (gftp_request * request, char *command, gpointer *data)
 {
+  gftp_config_vars * cv;
   char *pos, *backpos;
+  GList * templist;
   int i;
 
   if (command == NULL || *command == '\0')
     {
-      for (i=0; config_file_vars[i].key != NULL; i++)
+      for (templist = gftp_options_list; 
+           templist != NULL; 
+           templist = templist->next)
         {
-          if (!(config_file_vars[i].ports_shown & GFTP_PORT_TEXT))
-            continue;
+          cv = templist->data;
 
-          switch (config_file_vars[i].type)
+          for (i=0; cv[i].key != NULL; i++)
             {
-              case CONFIG_CHARTEXT:
-                printf ("%s = %s\n", config_file_vars[i].key, 
-                        *(char **) config_file_vars[i].var);
-                break;
-              case CONFIG_INTTEXT:
-              case CONFIG_CHECKBOX:
-                printf ("%s = %d\n", config_file_vars[i].key, 
-                        *(int *) config_file_vars[i].var);
-                break;
-              case CONFIG_FLOATTEXT:
-                printf ("%s = %.2f\n", config_file_vars[i].key, 
-                        *(float *) config_file_vars[i].var);
-                break;
+              if (!(cv[i].ports_shown & GFTP_PORT_TEXT))
+                continue;
+
+              if (*cv[i].key == '\0' || 
+                  gftp_option_types[cv[i].otype].write_function == NULL)
+                continue;
+
+              printf ("%s = ", cv[i].key);
+              gftp_option_types[cv[i].otype].write_function (&cv[i], stdout, 0);
+              printf ("\n");
             }
         }
     }
@@ -1058,48 +1058,24 @@
         *backpos = '\0';
       for (++pos; *pos == ' ' || *pos == '\t'; pos++);
 
-      for (i=0; config_file_vars[i].key != NULL; i++)
-        {
-          if (strcmp (config_file_vars[i].key, command) == 0)
-            break;
-           
-        }
-
-      if (config_file_vars[i].key == NULL)
+      if ((cv = g_hash_table_lookup (gftp_global_options_htable, command)) == NULL)
         {
           gftp_text_log (gftp_logging_error, NULL,
                          _("Error: Variable %s is not a valid configuration variable.\n"), command);
           return (1);
         }
 
-      if (!(config_file_vars[i].ports_shown & GFTP_PORT_TEXT))
+      if (!(cv->ports_shown & GFTP_PORT_TEXT))
         {
           gftp_text_log (gftp_logging_error, NULL,
                          _("Error: Variable %s is not available in the text port of gFTP\n"), command);
           return (1);
         }
 
-      configuration_changed = 1;
-      switch (config_file_vars[i].type)
+      if (gftp_option_types[cv->otype].read_function != NULL)
         {
-          case CONFIG_CHARTEXT:
-            if (*(char **) config_file_vars[i].var != NULL)
-              g_free (*(char **) config_file_vars[i].var);
-            *(char **) config_file_vars[i].var = g_strconcat (pos, NULL);
-            break;
-          case CONFIG_CHECKBOX:
-            *(int *) config_file_vars[i].var = *pos == '1' ? 1 : 0;
-            break;
-          case CONFIG_INTTEXT:
-            *(int *) config_file_vars[i].var = strtol (pos, NULL, 10);
-            break;
-          case CONFIG_FLOATTEXT:
-            *(float *) config_file_vars[i].var = strtod (pos, NULL);
-            break;
-          default:
-            gftp_text_log (gftp_logging_error, NULL,
-                           _("Error: You cannot change this variable\n"));
-            break;
+          configuration_changed = 1;
+          gftp_option_types[cv->otype].read_function (pos, cv, 1);
         }
     }
 
@@ -1195,57 +1171,6 @@
 
 
 void
-gftp_text_calc_kbs (gftp_transfer * tdata, ssize_t num_read)
-{
-  unsigned long waitusecs;
-  double difftime, curkbs;
-  gftp_file * tempfle;
-  struct timeval tv;
-  unsigned long toadd;
-
-  gettimeofday (&tv, NULL);
-
-  tempfle = tdata->curfle->data;
-  tdata->trans_bytes += num_read;
-  tdata->curtrans += num_read;
-  tdata->stalled = 0;
-
-  difftime = (tv.tv_sec - tdata->starttime.tv_sec) + ((double) (tv.tv_usec - tdata->starttime.tv_usec) / 1000000.0);
-  if (difftime == 0)
-    tdata->kbs = (double) tdata->trans_bytes / 1024.0;
-  else
-    tdata->kbs = (double) tdata->trans_bytes / 1024.0 / difftime;
-
-  difftime = (tv.tv_sec - tdata->lasttime.tv_sec) + ((double) (tv.tv_usec - tdata->lasttime.tv_usec) / 1000000.0);
-
-  if (difftime <= 0)
-    curkbs = (double) (num_read / 1024.0);
-  else
-    curkbs = (double) (num_read / 1024.0 / difftime);
-
-  if (tdata->fromreq->maxkbs > 0 && 
-      curkbs > tdata->fromreq->maxkbs)
-    {
-      waitusecs = (double) num_read / 1024.0 / tdata->fromreq->maxkbs * 1000000.0 - difftime;
-
-      if (waitusecs > 0)
-        {
-          difftime += ((double) waitusecs / 1000000.0);
-          usleep (waitusecs);
-        }
-    }
-
-  /* I don't call gettimeofday (&tdata->lasttime) here because this will use
-     less system resources. This will be close enough for what we need */
-  difftime += tdata->lasttime.tv_usec / 1000000.0;
-  toadd = (long) difftime;
-  difftime -= toadd;
-  tdata->lasttime.tv_sec += toadd;
-  tdata->lasttime.tv_usec = difftime * 1000000.0;
-}
-
-
-void
 sig_child (int signo)
 {
 }
@@ -1254,15 +1179,12 @@
 int
 gftp_text_set_show_subhelp (char *topic)
 {
-  int i;
+  gftp_config_vars * cv;
 
-  for (i=0; config_file_vars[i].key != NULL; i++)
+  if ((cv = g_hash_table_lookup (gftp_global_options_htable, topic)) != NULL)
     {
-      if (strcmp (topic, config_file_vars[i].key) == 0)
-        {
-          printf ("%s\n", config_file_vars[i].comment);
-          return (1);
-        }
+      printf ("%s\n", cv->comment);
+      return (1);
     }
 
   return (0);
--- a/src/text/gftp-text.h	Sat Apr 05 02:25:42 2003 +0000
+++ b/src/text/gftp-text.h	Sat Apr 05 16:30:45 2003 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*  gftp-text.h - include file for the gftp text port                        */
-/*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
+/*  Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org>                  */
 /*                                                                           */
 /*  This program is free software; you can redistribute it and/or modify     */
 /*  it under the terms of the GNU General Public License as published by     */
@@ -117,8 +117,6 @@
 						  char *buf,
 						  size_t size );
 int gftp_text_get_win_size 			( void );
-void gftp_text_calc_kbs 			( gftp_transfer * tdata, 
-						  ssize_t num_read );
 void sig_child 					( int signo );
 int gftp_text_set_show_subhelp			( char *topic );
 int gftp_text_clear_show_subhelp		( char *topic );