/**********************************************************************
 *
 * settings.cpp
 * Copyright (C) 1996
 * 
 * A component of the fnord webserver written by bmorin@wpi.edu.
 *
 * Altered for use with the Greenstone digital library software by the
 * New Zealand Digital Library Project at the University of Waikato,
 * New Zealand.
 *
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

#include "text_t.h"
#include "fileutil.h"

#if defined(GSDL_USE_OBJECTSPACE)
#  include <ospace\std\fstream>
#elif defined(GSDL_USE_IOS_H)
#  include <fstream.h>
#else
#  include <fstream>
#endif

#include <windows.h>
#include "httpsrv.h"
#include "settings.h"
#include "locate.h"
#include "resource.h"
#include "cgiwrapper.h"

// library settings
text_t gsdl_enterlib;
text_t gsdl_gsdlhome;
text_t gsdl_collecthome;
text_t gsdl_dbhome;
text_t gsdl_collections;
colinfo_tmap gsdl_collectinfo;

char gsdl_staticpages[MAX_FILENAME_SIZE];

// debug settings
char gsdl_log_name[MAX_FILENAME_SIZE] = "c:\\gsdl.log";
int gsdl_keep_log = 0;
int gsdl_show_console = 0;

// general settings
int gsdl_port_num = 8282;
int gsdl_external_access = 0;
int gsdl_auto_enter = 0;
int gsdl_browser = GS_DEFAULT;
char gsdl_browser_exe[MAX_FILENAME_SIZE] = "";
text_t gsdl_url;
text_t gsdl_conffile;
int gsdl_start_browser = 1;
int gsdl_address_resolution_method = 2;  // use localhost since users may switch between computers
				// The resolution method was previously on 1: Get an IP, but don't resolve to a name
text_t gsdl_host_IP;
text_t gsdl_mode_property_prefix;

// private data

// pathnames of the latest installed versions of netscape and
// internet explorer
static char netscape_exe[MAX_FILENAME_SIZE]="";
static char iexplore_exe[MAX_FILENAME_SIZE]="";

// pathname of the default browser
static char default_browser_exe[MAX_FILENAME_SIZE]="";

// whether netscape is needed (used in the settings dialog box)
static int gsdl_netscapeneeded = 0;

static void remove_end_slashes(char *str) {
  int len = strlen (str);
  while ((len > 0) && ((str[len-1] == '\\') || (str[len-1] == '/'))) {
    --len;
  }
  str[len] = '\0';
}

static void remove_end_slashes (text_t &str) {
  char *cstr = str.getcstr();
  remove_end_slashes (cstr);
  str = cstr;
  delete []cstr;
}

// returns 1 if successful, 0 otherwise
// checks for a file's existence
static int check_program_exe (char *path) {
  UINT curerrormode;
  OFSTRUCT reOpenBuff;
  int retvalue = 0;
  
  reOpenBuff.cBytes = sizeof (OFSTRUCT);
  
  curerrormode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  if (OpenFile(path, &reOpenBuff, OF_EXIST) != HFILE_ERROR) retvalue = 1;
  SetErrorMode(curerrormode);
  
  return retvalue;
}


// returns 1 if successful, 0 otherwise
static int get_default_browser_path (char *providedhtmltype, char *path, int maxsize) {
  HKEY hk1, hk2;
  char htmltype[256];
  long size;
  int retval = 0;
  
  htmltype[0] = '\0';
  path[0] = '\0';
  
  // try and get information about the default browser from the 
  // registry
  
  if (providedhtmltype != NULL) strcpy (htmltype, providedhtmltype);
  
  else if (RegOpenKey(HKEY_CLASSES_ROOT, ".htm", &hk1) == ERROR_SUCCESS) {
    size = 256;
    RegQueryValue(hk1, NULL, htmltype, &size);
    RegCloseKey(hk1);
  }
  
  if (RegOpenKey(HKEY_CLASSES_ROOT, htmltype, &hk1) == ERROR_SUCCESS) {
    if (RegOpenKey(hk1, "shell\\open", &hk2) == ERROR_SUCCESS) {
      // look for the command to start the browser
      size = maxsize;
      if (RegQueryValue(hk2,"command",path,&size) == ERROR_SUCCESS) {
				// strip all excess stuff off the command
	char endchar = ' ';
	int i = 0, len = 0;
	int state = 0; // 0=strip initial white-space and quotes, 1=grab path
	while (path[i] != '\0') {
	  if (state == 0) {
	    if (path[i] == ' ') {
	      // do nothing
	    } else if (path[i] == '"') {
	      endchar = '"';
	      state = 1;
	    } else {
	      state = 1;
	      path[len] = path[i];
	      ++len;
	    }
	  } else {
	    if (path[i] == endchar) break;
	    path[len] = path[i];
	    ++len;
	  }
	  ++i;
	}
	path[len] = '\0';
	
	// check the resulting pathname
	if (check_program_exe (path)) {
	  retval = 1; // succeeded
	} else {
	  path[0] = '\0'; // failed (must have been deleted or something...)
	}
      }
      RegCloseKey(hk2);
    }
    RegCloseKey(hk1);
  }
  
  return retval;
}


// returns 1 if successful, 0 otherwise
// note that appname should include .exe (e.g. netscape.exe)
static int registry_get_app_paths (char *appname, char *path, int maxsize) {
  HKEY hk1;
  long size;
  int retval = 0;
  
  path[0] = '\0';
  
  if (RegOpenKey(HKEY_LOCAL_MACHINE, 
		 "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths", 
		 &hk1) == ERROR_SUCCESS) {
    size = maxsize;
    if (RegQueryValue (hk1, appname, path, &size) == ERROR_SUCCESS &&
	check_program_exe (path));
    retval = 1;
    
    RegCloseKey(hk1);
  }
  
  return retval;
}

static void check_installed_browsers (int netscapeneeded) {
  netscape_exe[0] = '\0';
  iexplore_exe[0] = '\0';
  default_browser_exe[0] = '\0';
  
  // update the default browser information (if netscape isn't needed)
  if (!netscapeneeded) {
    get_default_browser_path (NULL, default_browser_exe, MAX_FILENAME_SIZE);
    _strlwr (default_browser_exe);
  }
  
  // look for netscape
  
  // first look for netscape in the registry
  if (!registry_get_app_paths("netscape.exe", netscape_exe, MAX_FILENAME_SIZE)) {
    // next look for "NetscapeMarkup"
    if (get_default_browser_path ("NetscapeMarkup", netscape_exe, MAX_FILENAME_SIZE)) {
      _strlwr (netscape_exe);
      if (!strstr (netscape_exe, "netscape.exe")) {
	netscape_exe[0] = '\0';
	
	// next look for \netscape\netscape.exe
	
	// get drive letter of the windows directory
	GetWindowsDirectory(netscape_exe, MAX_FILENAME_SIZE);
	netscape_exe[1] = '\0';
	strcat (netscape_exe, ":\\netscape\\netscape.exe");
	
	if (!check_program_exe (netscape_exe)) {
	  // lastly look for \netscape\program\netscape.exe
	  netscape_exe[1] = '\0';
	  strcat (netscape_exe, ":\\netscape\\program\\netscape.exe");
	  
	}
      }
    }
  }
  _strlwr (netscape_exe);
  if ((strlen (netscape_exe) > 0) && !check_program_exe (netscape_exe)) {
    netscape_exe[0] = '\0';  // couldn't find netscape
  }
  
  // look for internet explorer (if netscape isn't needed)
  
  // first look for iexplore in the registry
  if (!netscapeneeded && !registry_get_app_paths("iexplore.exe", 
						 iexplore_exe, MAX_FILENAME_SIZE)) {
    // next look for "htmlfile"
    if (get_default_browser_path ("htmlfile", iexplore_exe, MAX_FILENAME_SIZE)) {
      _strlwr (iexplore_exe);
      if (!strstr (iexplore_exe, "iexplore.exe")) {
	iexplore_exe[0] = '\0';
	
	// next look for \iexplore\iexplore.exe
	
	// get drive letter of the windows directory
	GetWindowsDirectory(iexplore_exe, MAX_FILENAME_SIZE);
	iexplore_exe[1] = '\0';
	strcat (iexplore_exe, ":\\iexplore\\iexplore.exe");
      }
    }
  }
  _strlwr (iexplore_exe);
  if ((strlen (iexplore_exe) > 0) && !check_program_exe (iexplore_exe)) {
    iexplore_exe[0] = '\0';  // couldn't find internet explorer
  }
}

void write_settings (const text_t url) {
  
  if (gsdl_conffile.empty()) {
    find_location();
    gsdl_conffile = filename_cat(data_location, "llssite.cfg");
  }

  char *conffile_c = gsdl_conffile.getcstr();
  ofstream fout (conffile_c);
  delete []conffile_c;
  if (fout) {
    
    outconvertclass text_t2ascii;

    // top (gsdl) level stuff
    fout << "[gsdl]\n";
    
    if (!url.empty()) {
      // url entry should only be written to llssite.cfg when the
      // server is actually running, not when it's stopped (since we
      // can't be sure what the url is at that stage). That is,
      // write_settings() is called with the url argument set when the
      // server first starts up, it's then called without url set as
      // the server shuts down.
      write_ini_line(fout, gsdl_mode_property_prefix+"url", url);      
    }

    write_ini_line(fout, "enterlib", gsdl_enterlib);
    write_ini_line(fout, "gsdlhome", gsdl_gsdlhome);
    write_ini_line(fout, "collecthome", gsdl_collecthome);
    write_ini_line(fout, "gdbmhome", gsdl_dbhome);
    
    write_ini_line(fout, "logfilename", gsdl_log_name);
    write_ini_line(fout, "keeplog", text_t(gsdl_keep_log));
    write_ini_line(fout, "consolelog", text_t(gsdl_show_console));
    
    write_ini_line(fout, "portnumber", text_t(gsdl_port_num));
    write_ini_line(fout, "externalaccess", text_t(gsdl_external_access));
    write_ini_line(fout, gsdl_mode_property_prefix+"autoenter", text_t(gsdl_auto_enter));
    write_ini_line(fout, "browser", text_t(gsdl_browser));
    write_ini_line(fout, "browserexe", gsdl_browser_exe);
    write_ini_line(fout, "collections", gsdl_collections);
    write_ini_line(fout, gsdl_mode_property_prefix+"start_browser", text_t(gsdl_start_browser));
    write_ini_line(fout, "address_resolution_method", text_t(gsdl_address_resolution_method));
    write_ini_line(fout, "hostIP", gsdl_host_IP);

    // collection levels
    colinfo_tmap::iterator here = gsdl_collectinfo.begin();
    colinfo_tmap::iterator end = gsdl_collectinfo.end();
    while (here != end) {
      fout << text_t2ascii << "[" << (*here).first << "]\n";
      if (!(*here).second.gsdl_gsdlhome.empty()) 
	write_ini_line(fout, "gsdlhome", (*here).second.gsdl_gsdlhome);
      if (!(*here).second.gsdl_collecthome.empty()) 
	write_ini_line(fout, "collecthome", (*here).second.gsdl_collecthome);
      if (!(*here).second.gsdl_dbhome.empty()) 
	write_ini_line(fout, "gdbmhome", (*here).second.gsdl_dbhome);
      
      ++here;
    }
    fout.close();
  }
}


// browser_compare assumes that check_exe is in lowercase
static int browser_compare (char *browser_exe_path, char *check_exe) {
  char tmp_exe[MAX_FILENAME_SIZE];
  strcpy (tmp_exe, browser_exe_path);
  _strlwr (tmp_exe);
  return (strstr (tmp_exe, check_exe) != NULL);
}

// This function assumes that check_installed_browsers
// has been recently called
// It also assumes that browser_exe is large
// enough to receive any path names to any browser
static void check_browser_settings (int &browser, char *browser_exe, 
				    int netscapeneeded) {
  // sort out which browser to use
  if ((browser == GS_NETSCAPE) && (netscape_exe[0] == '\0'))
    browser = GS_IEXPLORE;
  if ((browser == GS_IEXPLORE) && (netscapeneeded || (iexplore_exe[0] == '\0'))) {
    if (netscape_exe[0] != '\0') browser = GS_NETSCAPE;
    else browser = GS_OTHER;
  }
  if ((browser == GS_OTHER) && netscapeneeded && 
      !browser_compare (browser_exe, "netscape.exe") && (netscape_exe[0] != '\0')) {
    // this other browser isn't netscape and netscape is available
    browser = GS_NETSCAPE;
  }
  
  
  // get the browser's executable
  if (browser == GS_DEFAULT) {
    strcpy (browser_exe, default_browser_exe);
  } else if (browser == GS_NETSCAPE) {
    strcpy (browser_exe, netscape_exe);
  } else if (browser == GS_IEXPLORE) {
    strcpy (browser_exe, iexplore_exe);
  } else {
    browser = GS_OTHER;
    
    // if the browser should be netscape then check to
    // make sure it is
    if (netscapeneeded && !browser_compare (browser_exe, "netscape.exe")) {
      // not netscape, set to no browser
      browser_exe[0] = '\0';
    }
  }
}


static void revert_defaults (int netscapeneeded) {
  find_location();
  
  // library settings
  gsdl_enterlib = "/gsdl";
  gsdl_gsdlhome = data_location;
  gsdl_collecthome = filename_cat(data_location,"collect");
  gsdl_dbhome = data_location;
  
  // debug settings
  gsdl_keep_log = 0;
  char *cstr_value = filename_cat(data_location,"gsdl.log").getcstr();
  strcpy (gsdl_log_name, cstr_value); //strcpy (gsdl_log_name, "c:\\gsdl.log");
  delete []cstr_value;
  gsdl_show_console = 0;
  
  // general settings
  gsdl_port_num = 8282;
  gsdl_external_access = 0;
  if(gsdl_mode_property_prefix == "") {
	gsdl_auto_enter = 0;
	gsdl_start_browser = 1;
  } else {
	gsdl_auto_enter = 1;
	gsdl_start_browser = 0;
  }

  check_installed_browsers (netscapeneeded);
  gsdl_browser = GS_DEFAULT;
  strcpy (gsdl_browser_exe, default_browser_exe);
  check_browser_settings (gsdl_browser, gsdl_browser_exe, netscapeneeded);
}

void read_settings (int netscapeneeded) {
  
  if (gsdl_conffile.empty()) {
    find_location();
    gsdl_conffile = filename_cat(data_location, "llssite.cfg");
  }
  
  // set up defaults
  revert_defaults (netscapeneeded);
  
  text_t key, value, section;
  char *cstr_value;
  char *conffile_c = gsdl_conffile.getcstr();
#if defined (GSDL_USE_IOS_H)
  ifstream conf (conffile_c, ios::nocreate);
#else
  ifstream conf (conffile_c);
#endif
  delete []conffile_c;
  if (conf) {
    while (read_ini_line(conf, key, value) >= 0) {
      if (key.empty()) continue;
      if (value.empty() && starts_with(key, "[") && ends_with(key, "]")) {
	// should be a section title
	section = key;
	// remove square brackets
	section.erase (section.begin());
	section.erase (section.end()-1);

      } else {

	cstr_value = value.getcstr ();
      
	if (section == "gsdl") {

	  if (key == "enterlib") {
	    gsdl_enterlib = value;
	  
	    // 'logfilename' should occur in the configuration file
	    // before 'keeplog'
	  } else if (key == "logfilename") {
	    strcpy (gsdl_log_name, cstr_value);
	  
	  } else if (key == "keeplog") {
	    gsdl_keep_log = value.getint();
	    if (gsdl_keep_log) open_log_file();
	
	  } else if (key == "consolelog") {
	    if (value.getint()) activate_console();
	    else deactivate_console();
	
	  } else if (key == "portnumber") {
	    gsdl_port_num = value.getint();

	  } else if (key == "externalaccess") {
	    gsdl_external_access = value.getint();
	    
	  } else if (key == gsdl_mode_property_prefix+"autoenter") {
	    gsdl_auto_enter = value.getint();
	    
	  } else if (key == gsdl_mode_property_prefix+"start_browser") {
	    gsdl_start_browser = value.getint();
	
	  } else if (key == "browser") {
	    gsdl_browser = value.getint();
	
	  } else if (key == "browserexe") {
	    strcpy (gsdl_browser_exe, cstr_value);

	  } else if (key == "address_resolution_method") {
	    gsdl_address_resolution_method = value.getint();

	  } else if (key == "collections") {
	    gsdl_collections = value;
	  } 
	  // gsdlhome must occur in file before dbhome	    
	  else if (key == "gsdlhome") {
	    gsdl_gsdlhome = value;
	    gsdl_collecthome = filename_cat(value,"collect");
	    gsdl_dbhome = value;	  
	  } 
	  else if (key == "collecthome") {
	    gsdl_collecthome = value;
	  } 
	  else if (key == "gdbmhome") {
	    gsdl_dbhome = value;
	  }
	} else {
	  
	  // gsdlhome must occur in file before dbhome
	  if (key == "gsdlhome") {
	    gsdl_collectinfo[section].gsdl_gsdlhome = value;
	    gsdl_collectinfo[section].gsdl_collecthome = filename_cat(value,"collect");
	    gsdl_collectinfo[section].gsdl_dbhome = value;
	  } 
	  else if (key == "collecthome") {
	    gsdl_collectinfo[section].gsdl_collecthome = value;
	  }
	  else if (key == "gdbmhome") {
	    gsdl_collectinfo[section].gsdl_dbhome = value;
	  }
	}
	delete []cstr_value;
      }
    }
    conf.close();
  }
  
  // check the homes to make sure they don't contain
  // extra slashes at the end
  remove_end_slashes (gsdl_gsdlhome);
  remove_end_slashes (gsdl_collecthome);
  remove_end_slashes (gsdl_dbhome);
  colinfo_tmap::iterator here = gsdl_collectinfo.begin();
  colinfo_tmap::iterator end = gsdl_collectinfo.end();
  while (here != end) {
    remove_end_slashes ((*here).second.gsdl_gsdlhome);
    remove_end_slashes ((*here).second.gsdl_collecthome);
    remove_end_slashes ((*here).second.gsdl_dbhome);
    ++here;
  }

  // check the browser settings
  check_browser_settings (gsdl_browser, gsdl_browser_exe, netscapeneeded);
}

void gsdl_check_browser_settings (int netscapeneeded) {
  check_installed_browsers (netscapeneeded);
  check_browser_settings (gsdl_browser, gsdl_browser_exe, netscapeneeded);
}


static void dialog_update_enables (HWND hwndDlg) {
  int res;
  
  // if they want to use another browser, they should be able
  // edit its filename
  res = SendDlgItemMessage(hwndDlg, ID_RADIO_OTHER, BM_GETCHECK,0,0);
  SendDlgItemMessage(hwndDlg, ID_OTHER_NAME, WM_ENABLE, (res == 1), 0);
}


static int read_dialog_browser_field (HWND hwndDlg) {
  if (SendDlgItemMessage(hwndDlg, ID_RADIO_DEFAULT,
			 BM_GETCHECK, 0, 0) == 1) return GS_DEFAULT;
  if (SendDlgItemMessage(hwndDlg, ID_RADIO_NETSCAPE,
			 BM_GETCHECK, 0, 0) == 1) return GS_NETSCAPE;
  if (SendDlgItemMessage(hwndDlg, ID_RADIO_IE,
			 BM_GETCHECK, 0, 0) == 1) return GS_IEXPLORE;
  if (SendDlgItemMessage(hwndDlg, ID_RADIO_OTHER,
			 BM_GETCHECK, 0, 0) == 1) return GS_OTHER;
  return GS_NETSCAPE;
}


static void set_dialog_browser_field (HWND hwndDlg, int browser, char *othername) {
  // if we are trying to set the browser to default, netscape or
  // internet explorer and we can't find them, set the browser
  // to 'other'
  if ((browser == GS_DEFAULT) && (default_browser_exe[0] == '\0'))
    browser = GS_NETSCAPE;
  if ((browser == GS_NETSCAPE) && (netscape_exe[0] == '\0'))
    browser = GS_IEXPLORE;
  if ((browser == GS_IEXPLORE) && (iexplore_exe[0] == '\0')) {
    if (netscape_exe[0] != '\0') browser = GS_NETSCAPE;
    else browser = GS_OTHER;
  }
  
  // update the radio buttons
  SendDlgItemMessage(hwndDlg, ID_RADIO_DEFAULT, BM_SETCHECK,
		     (browser == GS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED, 0);
  SendDlgItemMessage(hwndDlg, ID_RADIO_NETSCAPE, BM_SETCHECK,
		     (browser == GS_NETSCAPE) ? BST_CHECKED : BST_UNCHECKED, 0);
  SendDlgItemMessage(hwndDlg, ID_RADIO_IE, BM_SETCHECK,
		     (browser == GS_IEXPLORE) ? BST_CHECKED : BST_UNCHECKED, 0);
  SendDlgItemMessage(hwndDlg, ID_RADIO_OTHER, BM_SETCHECK,
		     (browser == GS_OTHER) ? BST_CHECKED : BST_UNCHECKED, 0);
  
  // update the other name field
  if (browser == GS_DEFAULT) {
    SetDlgItemText(hwndDlg, ID_OTHER_NAME, default_browser_exe);
  } else if (browser == GS_NETSCAPE) {
    SetDlgItemText(hwndDlg, ID_OTHER_NAME, netscape_exe);
  } else if (browser == GS_IEXPLORE) {
    SetDlgItemText(hwndDlg, ID_OTHER_NAME, iexplore_exe);
  } else if (othername != NULL) {
    SetDlgItemText(hwndDlg, ID_OTHER_NAME, othername);
  }
}


static void read_browser_exe_field (HWND hwndDlg, char *filename, int maxsize) {
  filename[0] = '\0';
  GetDlgItemText(hwndDlg, ID_OTHER_NAME, filename, maxsize);
}

static int read_address_resolution_field (HWND hwndDlg) {
  if (SendDlgItemMessage(hwndDlg, ID_ARM_NAME,
			 BM_GETCHECK, 0, 0) == 1) return ARM_NAME;
  if (SendDlgItemMessage(hwndDlg, ID_ARM_IP,
			 BM_GETCHECK, 0, 0) == 1) return ARM_IP;
  if (SendDlgItemMessage(hwndDlg, ID_ARM_LOCALHOST,
			 BM_GETCHECK, 0, 0) == 1) return ARM_LOCALHOST;
  if (SendDlgItemMessage(hwndDlg, ID_ARM_127_0_0_1,
			 BM_GETCHECK, 0, 0) == 1) return ARM_127_0_0_1;
  return ARM_NAME;
}

static void set_address_resolution_field (HWND hwndDlg, 
					  int address_res_method) {
  // update the radio buttons
  SendDlgItemMessage(hwndDlg, ID_ARM_NAME, BM_SETCHECK,
		     (address_res_method == ARM_NAME) ? BST_CHECKED : BST_UNCHECKED, 0);
  SendDlgItemMessage(hwndDlg, ID_ARM_IP, BM_SETCHECK,
		     (address_res_method == ARM_IP) ? BST_CHECKED : BST_UNCHECKED, 0);
  SendDlgItemMessage(hwndDlg, ID_ARM_LOCALHOST, BM_SETCHECK,
		     (address_res_method == ARM_LOCALHOST) ? BST_CHECKED : BST_UNCHECKED, 0);
  SendDlgItemMessage(hwndDlg, ID_ARM_127_0_0_1, BM_SETCHECK,
		     (address_res_method == ARM_127_0_0_1) ? BST_CHECKED : BST_UNCHECKED, 0);

}

static void read_dialog_fields (HWND hwndDlg) {
  int res;  BOOL bres;
  
  // port number
  gsdl_port_num = GetDlgItemInt(hwndDlg, SERVER_PORT_EDIT_BOX, &bres, 0);
  if (!bres) gsdl_port_num = 8282;

  // whether to allow external access or not
  res = SendDlgItemMessage(hwndDlg, ID_EXTERNAL_ACCESS, BM_GETCHECK, 0, 0);
  gsdl_external_access = (res == 1);
    
  // whether to enter the library automatically on startup
  res = SendDlgItemMessage(hwndDlg, ID_AUTO_ENTER_LIBRARY, BM_GETCHECK, 0, 0);
  gsdl_auto_enter = (res == 1);

  // which browser to use
  gsdl_browser = read_dialog_browser_field (hwndDlg);
  
  // find out where the browser exe lives
  read_browser_exe_field (hwndDlg, gsdl_browser_exe, MAX_FILENAME_SIZE);

  // which address resolution method
  gsdl_address_resolution_method = read_address_resolution_field(hwndDlg);
}




static BOOL CALLBACK dialog_proc(HWND hwndDlg, UINT uMsg, 
				 WPARAM wParam,LPARAM  lParam) {
  int wNotifyCode = HIWORD(wParam);
  int wID = LOWORD(wParam);
  char *filefilter = "Program Files (*.exe)\0*.exe\0All Files (*.*)\0*.*\0\0";
  OPENFILENAME fname;
  char filename[MAX_FILENAME_SIZE];
  
  switch (uMsg) {
  case WM_INITDIALOG:
    // set current values
    SetDlgItemInt(hwndDlg, SERVER_PORT_EDIT_BOX, gsdl_port_num, FALSE);
    SendDlgItemMessage(hwndDlg, ID_EXTERNAL_ACCESS, BM_SETCHECK,
		       gsdl_external_access ? 1 : 0, 0);
    SendDlgItemMessage(hwndDlg, ID_AUTO_ENTER_LIBRARY, BM_SETCHECK,
		       gsdl_auto_enter ? 1 : 0, 0);
    set_dialog_browser_field (hwndDlg, gsdl_browser, gsdl_browser_exe);
    set_address_resolution_field(hwndDlg, gsdl_address_resolution_method);
    dialog_update_enables(hwndDlg);
    
    // make sure that the default browser, netscape and internet explorer
    // radio buttons are only enabled if they could be found
    if (default_browser_exe[0] == '\0')
      EnableWindow (GetDlgItem (hwndDlg, ID_RADIO_DEFAULT), FALSE);
    if (netscape_exe[0] == '\0')
      EnableWindow (GetDlgItem (hwndDlg, ID_RADIO_NETSCAPE), FALSE);
    if (iexplore_exe[0] == '\0')
      EnableWindow (GetDlgItem (hwndDlg, ID_RADIO_IE), FALSE);
    
    return 1;
    
  case WM_COMMAND:
    if (wNotifyCode == BN_CLICKED) {
      switch (wID) {
      case ID_CANCEL_BUTTON:
	EndDialog(hwndDlg, 0);
	return 1;
	
      case ID_OK_BUTTON:
	// check to make sure we can find the browser
	filename[0] = '\0';
	read_browser_exe_field (hwndDlg, filename, MAX_FILENAME_SIZE);
	if (check_program_exe (filename)) { 
	  // the file exists
	  // if netscape is needed, make sure the browser is netscape
	  _strlwr(filename);
	  if (!gsdl_netscapeneeded || strstr (filename, "netscape.exe") != NULL) {
	    // everything is ok
	    read_dialog_fields(hwndDlg);
	    EndDialog(hwndDlg, 1);
	    
	  } else {
	    // message: must use netscape with this version
	    MessageBox(hwndDlg,
		       "You are using this software on a machine which\n"
		       "currently does not have a working TCP/IP network layer.\n"
		       "To allow the Greenstone Digital Library software to use\n"
		       "its own TCP/IP network layer you must use a Netscape\n"
		       "web browser.",
		       "Greenstone Digital Library Software",
		       MB_OK|MB_APPLMODAL);
	  }
	} else {
	  // message: the file did not exist
	  MessageBox(hwndDlg,
		     "Could not find the selected browser. You must have a\n"
		     "web browser installed to use the Greenstone Digital\n"
		     "Library software.",
		     "Greenstone Digital Library Software",
		     MB_OK|MB_APPLMODAL);
	}
	return 1;

      case ID_RADIO_DEFAULT:
	set_dialog_browser_field (hwndDlg, GS_DEFAULT, NULL);
	dialog_update_enables(hwndDlg);
	return 1;
	
      case ID_RADIO_NETSCAPE:
	set_dialog_browser_field (hwndDlg, GS_NETSCAPE, NULL);
	dialog_update_enables(hwndDlg);
	return 1;
	
      case ID_RADIO_IE:
	set_dialog_browser_field (hwndDlg, GS_IEXPLORE, NULL);
	dialog_update_enables(hwndDlg);
	return 1;
	
      case ID_RADIO_OTHER:
	set_dialog_browser_field (hwndDlg, GS_OTHER, NULL);
	dialog_update_enables(hwndDlg);
	return 1;
	
      case ID_BROWSE_BUTTON:
	filename[0] = '\0';
	memset(&fname, 0, sizeof(OPENFILENAME));
	fname.lStructSize = sizeof(OPENFILENAME);
	fname.hwndOwner = hwndDlg;
	fname.hInstance = NULL;
	fname.lpstrFilter = filefilter;
	fname.lpstrCustomFilter = NULL;
	fname.nMaxCustFilter = 0;
	fname.nFilterIndex = 1;
	fname.lpstrFile = filename;
	fname.nMaxFile = MAX_FILENAME_SIZE-1;
	fname.lpstrFileTitle = NULL;
	fname.nMaxFileTitle = 0;
	fname.lpstrInitialDir = NULL;
	fname.lpstrTitle = "Choose Web Browser";
	fname.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	
	if(GetOpenFileName(&fname)) {
	  set_dialog_browser_field (hwndDlg, GS_OTHER, filename);
	  dialog_update_enables(hwndDlg);
	}
	return 1;

      case ID_ARM_NAME:
	set_address_resolution_field (hwndDlg, ARM_NAME);
	dialog_update_enables(hwndDlg);
	return 1;
     case ID_ARM_IP:
	set_address_resolution_field (hwndDlg, ARM_IP);
	dialog_update_enables(hwndDlg);
	return 1;
    case ID_ARM_LOCALHOST:
	set_address_resolution_field (hwndDlg, ARM_LOCALHOST);
	dialog_update_enables(hwndDlg);
	return 1;
     case ID_ARM_127_0_0_1:
	set_address_resolution_field (hwndDlg, ARM_127_0_0_1);
	dialog_update_enables(hwndDlg);
	return 1;

      }
    }
    return 0;
    
  case WM_CLOSE:
  case WM_DESTROY:
    EndDialog(hwndDlg, 0);
    return 1;
  }
  
  return 0;
}

static void dialog_debug_update_enables (HWND hwndDlg) {
  int res;
  
  // if they want a log of program use allow them to
  // edit its filename
  res = SendDlgItemMessage(hwndDlg, LOG_CHECK, BM_GETCHECK,0,0);
  SendDlgItemMessage(hwndDlg, LOG_NAME_BOX, WM_ENABLE, (res == 1), 0);
}


static void read_dialog_debug_fields (HWND hwndDlg) {
  int res;
  
  // whether to log program use
  res = SendDlgItemMessage(hwndDlg, LOG_CHECK, BM_GETCHECK,0,0);
  gsdl_keep_log = (res == 1);
  
  // log filename
  res = SendDlgItemMessage(hwndDlg, LOG_NAME_BOX, EM_GETMODIFY,0,0);
  if (res != 0) {
    res = GetDlgItemText(hwndDlg, LOG_NAME_BOX, gsdl_log_name, MAX_FILENAME_SIZE);
  }
  
  // whether to display log information on console
  res = SendDlgItemMessage(hwndDlg, CONSOLE_CHECK, BM_GETCHECK,0,0);
  gsdl_show_console = (res == 1);
}


static BOOL CALLBACK dialog_debug_proc(HWND hwndDlg, UINT uMsg, 
				       WPARAM wParam,LPARAM  lParam) {
  int wNotifyCode = HIWORD(wParam);
  int wID = LOWORD(wParam);
  
  switch (uMsg) {
  case WM_INITDIALOG:
    // set current values
    SendDlgItemMessage(hwndDlg, LOG_CHECK, BM_SETCHECK,
		       gsdl_keep_log ? 1 : 0, 0);
    SetDlgItemText(hwndDlg, LOG_NAME_BOX, gsdl_log_name);
    SendDlgItemMessage(hwndDlg, CONSOLE_CHECK, BM_SETCHECK,
		       gsdl_show_console ? 1 : 0, 0);
    dialog_debug_update_enables(hwndDlg);
    return 1;
    
  case WM_COMMAND:
    if (wNotifyCode == BN_CLICKED) {
      switch (wID) {
      case ID_CANCEL_BUTTON:
	EndDialog(hwndDlg, 0);
	return 1;
	
      case ID_OK_BUTTON:
	read_dialog_debug_fields(hwndDlg);
	EndDialog(hwndDlg, 1);
	return 1;
	
      case LOG_CHECK:
	dialog_debug_update_enables(hwndDlg);
	return 1;
      }
    }
    return 0;
    
  case WM_CLOSE:
  case WM_DESTROY:
    EndDialog(hwndDlg, 0);
    return 1;
  }
  
  return 0;
}


void Settings_Dialog(HWND window, int netscapeneeded)
{
  int old_gsdl_show_console = gsdl_show_console;
  int old_gsdl_port_num = gsdl_port_num;
  int old_gsdl_external_access = gsdl_external_access;
  
  int res = 0;
  
  gsdl_netscapeneeded = netscapeneeded;
  
  if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && 
      (GetAsyncKeyState(VkKeyScan('d')) & 0x8000)) {
    // control-D was pressed, display debug settings
    // dialog box
    res = DialogBox (NULL, MAKEINTRESOURCE(COMMS_DIALOG_DEBUG),
		     window, (DLGPROC)dialog_debug_proc);
    
    if (res == 1) {
      // only update if exited via the OK button
      if (gsdl_keep_log) open_log_file(); 
      else close_log_file();
      
      // turn the console on/off if we need to
      if (gsdl_show_console != old_gsdl_show_console) {
	if (gsdl_show_console) activate_console ();
	else deactivate_console ();
      }
    }
    
  } else {
    // display normal settings dialog box
    
    // make sure everything is up-to-date
    gsdl_check_browser_settings (netscapeneeded);
    
    res = DialogBox (NULL, MAKEINTRESOURCE(COMMS_DIALOG2),
		     window, (DLGPROC)dialog_proc);

    if (res == 1) {
      // only update if exited via the OK button
      if ((gsdl_port_num != old_gsdl_port_num) 
	  || (gsdl_external_access != old_gsdl_external_access)) {
	EndHTTPServer();
	StartHTTPServer(window);
      }
    }
  }
  
  // save the settings if we exited via the ok button
  if (res == 1) {
    write_settings(gsdl_url);
    // reset httpprefix in case port number was changed
    //    configure_httpprefix ();
  }
}
