/* Nessus
 * Copyright (C) 1998 Renaud Deraison
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * 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.
 *
 * In addition, as a special exception, Renaud Deraison
 * gives permission to link the code of this program with any
 * version of the OpenSSL library which is distributed under a
 * license identical to that listed in the included COPYING.OpenSSL
 * file, and distribute linked combinations including the two.
 * You must obey the GNU General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * this file, you may extend this exception to your version of the
 * file, but you are not obligated to do so.  If you do not wish to
 * do so, delete this exception statement from your version.
 */

#include <includes.h>

#include "nessus_i18n.h"
#include "nessus_plugin.h"

#ifdef USE_GTK
#include "comm.h"
#include <gtk/gtk.h>
#include "xstuff.h"
#include "context.h"
#include "preferences.h"
#include "sighand.h"
#include "prefs_dialog_auth.h"
#include "prefs_dialog_prefs.h"
#include "prefs_help.h"
#include "prefs_dialog.h"
#include "prefs_context.h"
#include "prefs_scope_tree.h"
#include "prefs_about.h"
#include "prefs_comment.h"
#include "prefs_options.h"
#include "prefs_report.h"
#include "prefs_scan_assistant.h"
#include "prefs_comment.h"

#ifdef ENABLE_SAVE_KB
# include "prefs_kb.h"
#endif

#include "error_dialog.h"
#include "monitor_dialog.h"
#include "report.h"
#include "report_save.h"
#include "read_target_file.h"
#include "globals.h"

#include "../xpm/connect_16.xpm"
#include "../xpm/connect_24.xpm"
#include "../xpm/disconnect_16.xpm"
#include "../xpm/disconnect_24.xpm"
#include "../xpm/general_prefs.xpm"
#include "../xpm/credentials.xpm"
#include "../xpm/plugins.xpm"
#include "../xpm/knowledgebase.xpm"
#include "../xpm/access_rules.xpm"
#include "../xpm/properties.xpm"
#include "../xpm/target_selection.xpm"


static void prefs_dialog_set_tooltips(struct arglist *);

/*
 * launch the users manual pdf document with the configure
 * pdf viewer.
 */
void
show_users_manual(menuitem, ctrls)
  GtkWidget *menuitem;
  gpointer ctrls;
{
#ifdef NESSUS_DOCDIR
  char * dir = NESSUS_DOCDIR;
#else
  char * dir = "";
#endif
  /* the pdf file is covered by gettext to allow
   * speficication of translation in the respective po
   * files rather than in the source code. */
  char * fname = _("users-manual.pdf");
  char * path = g_build_filename(dir, fname, NULL);

  show_pdf(path);
  g_free(path);
}

/*
 * Save the current global settings to ~/.nessusrc
 */
void
save_global_settings(menuitem, ctrls)
  GtkWidget *menuitem;
  gpointer ctrls;
{
  prefs_dialog_apply(Global, ctrls);
  prefs_dialog_apply_plugin_prefs(Global->plugins);
  prefs_dialog_apply_plugin_prefs(Global->scanners);
  context_sync_plugin_prefs(Global);
  preferences_save(Global);
  show_info(_("The global settings have been saved."));
}

/*
 * Toggle Toolbar on/off
 */
void
toggle_toolbar(menuitem, ctrls)
  GtkWidget *menuitem;
  struct arglist *ctrls;
{
  GtkWidget *toolbar = arg_get_value(ctrls, "TOOLBAR");

  if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
  {
    prefs_set_int(Global, "hide_toolbar", 0);
    gtk_widget_show(toolbar);
  }
  else
  {
    prefs_set_int(Global, "hide_toolbar", 1);
    gtk_widget_hide(toolbar);
  }
}

/*
 * Toggle Message-Log on/off
 */
void
toggle_msglog(menuitem, ctrls)
  GtkWidget *menuitem;
  struct arglist *ctrls;
{
  GtkWidget *msglogframe = arg_get_value(ctrls, "MSGLOGFRAME");

  if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
  {
    prefs_set_int(Global, "hide_msglog", 0);
    gtk_widget_show(msglogframe);
  }
  else
  {
    prefs_set_int(Global, "hide_msglog", 1);
    gtk_widget_hide(msglogframe);
  }
}


/*
 * Menu items
 */
void
menuitem_TODO(menuitem, ctrls)
  GtkWidget *menuitem;
  struct arglist *ctrls;
{
  show_error(_("Not yet implemented."));
}

void
menuitem_add(menuitem, menu, name, stockicon, func)
  GtkWidget *menuitem;
  GtkWidget *menu;
  const gchar *name;
  const gchar *stockicon;
  GtkSignalFunc func;
{
  GtkWidget *icon;

  gtk_widget_show(menuitem);
  gtk_container_add(GTK_CONTAINER(menu), menuitem);
  if(name)
    arg_add_value(MainDialog, name, ARG_PTR, -1, menuitem);
  if(stockicon)
  {
    icon = gtk_image_new_from_stock(stockicon, GTK_ICON_SIZE_MENU);
    gtk_widget_show(icon);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), icon);
  }
  if(func)
    gtk_signal_connect(GTK_OBJECT(menuitem), "activate", func, MainDialog);
}

void
menuitem_separator(menu)
  GtkWidget *menu;
{
  GtkWidget *menuitem;

  menuitem = gtk_menu_item_new();
  menuitem_add(menuitem, menu, NULL, NULL, NULL);
  gtk_widget_set_sensitive(menuitem, FALSE);
}


/* Add a pair of new "stock" icons to the factory.
 *
 * The parameters small and large are the arrays of char* that make up
 * an xpm.  The icons are added to the factory as an icon set for the
 * given stock id.  The small icon is used as the default icon for the
 * size GTK_ICON_SIZE_MENU and the large one is the default icon for the
 * whole set and the default icon for the size
 * GTK_ICON_SIZE_LARGE_TOOLBAR.
 *
 * The parameter small may be NULL to indicate that no special small
 * variant exists.
 */
static void
add_nessus_icon_set(factory, stock_id, large, small)
  GtkIconFactory *factory;
  const char *stock_id;
  const char **large;
  const char **small;
{
  GtkIconSet *iconset;
  GtkIconSource *source;
  GdkPixbuf *pixbuf;

  /* The "large" icon is used as the default icon and the icon for the
   * GTK_ICON_SIZE_LARGE_TOOLBAR size */
  pixbuf = gdk_pixbuf_new_from_xpm_data(large);
  iconset = gtk_icon_set_new_from_pixbuf(pixbuf);

  source = gtk_icon_source_new();
  gtk_icon_source_set_pixbuf(source, pixbuf);
  gtk_icon_source_set_size_wildcarded(source, FALSE);
  gtk_icon_source_set_size(source, GTK_ICON_SIZE_LARGE_TOOLBAR);
  gtk_icon_set_add_source(iconset, source);
  gtk_icon_source_free(source);
  g_object_unref(G_OBJECT(pixbuf));

  /* The "small" icon is used for the GTK_ICON_SIZE_MENU size */
  if (small != NULL)
  {
    pixbuf = gdk_pixbuf_new_from_xpm_data(small);
    source = gtk_icon_source_new();
    gtk_icon_source_set_pixbuf(source, pixbuf);
    gtk_icon_source_set_size_wildcarded(source, FALSE);
    gtk_icon_source_set_size(source, GTK_ICON_SIZE_MENU);
    gtk_icon_set_add_source(iconset, source);
    gtk_icon_source_free(source);
    g_object_unref(G_OBJECT(pixbuf));
  }

  gtk_icon_factory_add(factory, stock_id, iconset);
}  

/* Create some nessus specific stock icons.
 *
 * This function adds two stock icon sets, "nessus-connect" and
 * "nessus-disconnect" so that they can be used for menu items or
 * buttons.
 */
static void
create_nessus_icon_factory()
{
  GtkIconFactory* factory = gtk_icon_factory_new();

  add_nessus_icon_set(factory, "nessus-connect", connect_24, connect_16);
  add_nessus_icon_set(factory, "nessus-disconnect", disconnect_24,
      disconnect_16);
  add_nessus_icon_set(factory, "nessus-general-prefs", general_prefs_xpm, NULL);
  add_nessus_icon_set(factory, "nessus-plugins", plugins_xpm, NULL);
  add_nessus_icon_set(factory, "nessus-credentials", credentials_xpm, NULL);
  add_nessus_icon_set(factory, "nessus-target-selection", target_selection_xpm,
      NULL);
  add_nessus_icon_set(factory, "nessus-access-rules", access_rules_xpm, NULL);
  add_nessus_icon_set(factory, "nessus-prefs", properties_xpm, NULL);
  add_nessus_icon_set(factory, "nessus-knowledge-base", knowledgebase_xpm,
      NULL);

  gtk_icon_factory_add_default(factory);
  g_object_unref(G_OBJECT(factory));
}

/*
 * prefs_dialog_setup
 * 
 * This function draws the preferences dialog of the Nessus
 * client
 *
 */
void
prefs_dialog_setup(context)
  struct context *context;
{
  GtkWidget *window;
  GtkWidget *mainmenu;
  GtkWidget *menuitem;
  GtkWidget *submenu;
  GtkWidget *subsubmenu;
  GtkWidget *notebook;
  GtkWidget *label;
  GtkWidget *frame;
  GtkWidget *box;
  GtkWidget *hbox;
  GtkWidget *vbox;
  GtkWidget *msglogframe;
  GtkWidget *icon;
  GtkWidget *toolbar_button;
  GtkWidget *toolbar;
  GtkWidget *scrolledwindow;
  GtkWidget *textview;
  GtkWidget *hpaned;
  GtkWidget *statusbar;
  GtkAccelGroup *accel_group;
  struct arglist *prefs_scope_tree;
  struct arglist *prefs_comment;
  struct arglist *prefs_options;
  struct arglist *prefs_report;
  struct arglist *ctrls = emalloc(sizeof(struct arglist));


  MainDialog = ctrls;

  create_nessus_icon_factory();

/*
 * We draw the window ....
 */
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(G_OBJECT(window), "delete_event",
      G_CALLBACK(gtk_main_quit), NULL);
  g_signal_connect(G_OBJECT(window), "delete_event",
      G_CALLBACK(gtk_widget_hide_on_delete), NULL);

  gtk_window_set_title(GTK_WINDOW(window), _("Nessus Client"));
  arg_add_value(ctrls, "WINDOW", ARG_PTR, -1, window);
  arg_add_value(ctrls, "CONTEXT", ARG_PTR, -1, window);
  /*
   * We put a vbox in it...
   */
  box = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(window), box);
  gtk_widget_show(box);

/*
 * Main menu
 */
  accel_group = gtk_accel_group_new();
  gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);

  mainmenu = gtk_menu_bar_new();
  gtk_widget_show(mainmenu);
  gtk_box_pack_start(GTK_BOX(box), mainmenu, FALSE, FALSE, 0);


  /* File menu */
  menuitem = gtk_menu_item_new_with_mnemonic(_("_File"));
  menuitem_add(menuitem, mainmenu, NULL, NULL, NULL);
  submenu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

  menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Connect"));
  menuitem_add(menuitem, submenu, "CONNECT_MENUITEM", "nessus-connect",
      GTK_SIGNAL_FUNC(prefs_dialog_auth_connect));

  menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Disconnect"));
  menuitem_add(menuitem, submenu, "DISCONNECT_MENUITEM", "nessus-disconnect",
      GTK_SIGNAL_FUNC(prefs_dialog_auth_disconnect));
  gtk_widget_set_sensitive(menuitem, FALSE);

  menuitem_separator(submenu);

  menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Scan Assistant"));
  menuitem_add(menuitem, submenu, NULL, "gtk-help",
      GTK_SIGNAL_FUNC(prefs_scan_assistant));

  menuitem = gtk_image_menu_item_new_from_stock("gtk-preferences", accel_group);
  menuitem_add(menuitem, submenu, "PREFERENCES_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(prefs_dialog_prefs));

  menuitem = gtk_image_menu_item_new_with_mnemonic(_("Save _Global Settings"));
  menuitem_add(menuitem, submenu, NULL, "gtk-save",
      GTK_SIGNAL_FUNC(save_global_settings));

  menuitem_separator(submenu);

  menuitem = gtk_image_menu_item_new_from_stock("gtk-quit", accel_group);
  menuitem_add(menuitem, submenu, NULL, NULL,
      GTK_SIGNAL_FUNC(gtk_main_quit));


  /* View menu */
  menuitem = gtk_menu_item_new_with_mnemonic(_("_View"));
  menuitem_add(menuitem, mainmenu, NULL, NULL, NULL);
  submenu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

  menuitem = gtk_check_menu_item_new_with_mnemonic(_("_Toolbar"));
  menuitem_add(menuitem, submenu, "TOGGLETOOLBAR_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(toggle_toolbar));

  menuitem = gtk_check_menu_item_new_with_mnemonic(_("_Message log"));
  menuitem_add(menuitem, submenu, "TOGGLEMSGLOG_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(toggle_msglog));


  /* Task menu */
  menuitem = gtk_menu_item_new_with_mnemonic(_("_Task"));
  menuitem_add(menuitem, mainmenu, NULL, NULL, NULL);
  submenu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

  menuitem = gtk_image_menu_item_new_with_mnemonic(_("_New"));
  menuitem_add(menuitem, submenu, NULL, "gtk-new",
      GTK_SIGNAL_FUNC(task_menu_new));

  menuitem = gtk_menu_item_new_with_mnemonic(_("_Rename"));
  menuitem_add(menuitem, submenu, "RENAMETASK_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(task_menu_rename));

  menuitem = gtk_image_menu_item_new_from_stock("gtk-delete", accel_group);
  menuitem_add(menuitem, submenu, "DELETETASK_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(task_menu_delete));


  /* Scope menu */
  menuitem = gtk_menu_item_new_with_mnemonic(_("_Scope"));
  menuitem_add(menuitem, mainmenu, NULL, NULL, NULL);
  submenu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

  menuitem = gtk_image_menu_item_new_from_stock("gtk-execute", accel_group);
  menuitem_add(menuitem, submenu, "EXECSCOPE_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(prefs_dialog_execute));

#if 0
  menuitem = gtk_image_menu_item_new_from_stock("gtk-stop", accel_group);
  menuitem_add(menuitem, submenu, "STOPSCOPE_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(menuitem_TODO));
  gtk_widget_set_sensitive(menuitem, FALSE);
#endif

  menuitem_separator(submenu);

  menuitem = gtk_image_menu_item_new_with_mnemonic(_("_New"));
  menuitem_add(menuitem, submenu, "NEWSCOPE_MENUITEM", "gtk-new",
      GTK_SIGNAL_FUNC(scope_menu_new));

  menuitem = gtk_menu_item_new_with_mnemonic(_("_Rename"));
  menuitem_add(menuitem, submenu, "RENAMESCOPE_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(scope_menu_rename));

  menuitem = gtk_image_menu_item_new_from_stock("gtk-delete", accel_group);
  menuitem_add(menuitem, submenu, "DELETESCOPE_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(scope_menu_delete));

  /* Scope -> Move to task */
  menuitem = gtk_menu_item_new_with_mnemonic(_("_Move to task"));
  menuitem_add(menuitem, submenu, "MOVESCOPE_MENUITEM", NULL, NULL);
  subsubmenu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), subsubmenu);
  arg_add_value(ctrls, "MOVESCOPE_SUBMENU", ARG_PTR, -1, subsubmenu);

  menuitem_separator(submenu);

  menuitem = gtk_image_menu_item_new_from_stock("gtk-open", NULL);
  menuitem_add(menuitem, submenu, "OPENSCOPE_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(scope_menu_open));

  menuitem = gtk_image_menu_item_new_from_stock("gtk-save-as", NULL);
  menuitem_add(menuitem, submenu, "SAVESCOPE_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(scope_menu_save));


  /* Report menu */
  menuitem = gtk_menu_item_new_with_mnemonic(_("_Report"));
  menuitem_add(menuitem, mainmenu, NULL, NULL, NULL);
  submenu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

  menuitem = gtk_menu_item_new_with_mnemonic(_("_Rename"));
  menuitem_add(menuitem, submenu, "RENAMEREPORT_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(report_menu_rename));

  menuitem = gtk_image_menu_item_new_from_stock("gtk-delete", accel_group);
  menuitem_add(menuitem, submenu, "DELETEREPORT_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(report_menu_delete));

  menuitem_separator(submenu);

  menuitem = gtk_menu_item_new_with_mnemonic(_("_Import"));
  menuitem_add(menuitem, submenu, "IMPORTREPORT_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(open_report_selectfile));

  menuitem = gtk_menu_item_new_with_mnemonic(_("E_xport"));
  menuitem_add(menuitem, submenu, "EXPORTREPORT_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(report_save_cb));

  menuitem = gtk_image_menu_item_new_from_stock("gtk-print", accel_group);
  menuitem_add(menuitem, submenu, "PRINTREPORT_MENUITEM", NULL,
      GTK_SIGNAL_FUNC(report_open_pdf));


  /* Help menu */
  menuitem = gtk_menu_item_new_with_mnemonic(_("_Help"));
  menuitem_add(menuitem, mainmenu, NULL, NULL, NULL);
  submenu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

  menuitem = gtk_menu_item_new_with_mnemonic(_("_Users Manual"));
  menuitem_add(menuitem, submenu, NULL, NULL,
      GTK_SIGNAL_FUNC(show_users_manual));

  menuitem = gtk_menu_item_new_with_mnemonic(_("_About"));
  menuitem_add(menuitem, submenu, NULL, NULL,
      GTK_SIGNAL_FUNC(prefs_dialog_about));





/* hbox with toolbar+scopetree-vbox and notebook */

  hbox = gtk_hbox_new(FALSE, 4);
  gtk_widget_show(hbox);
  gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);

  hpaned = gtk_hpaned_new();
  gtk_widget_ref(hpaned);
  gtk_paned_set_position(GTK_PANED(hpaned), 210);
  gtk_widget_show(hpaned);
  gtk_box_pack_start(GTK_BOX(hbox), hpaned, TRUE, TRUE, 0);

  gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);

  vbox = gtk_vbox_new(FALSE, 0);
  gtk_widget_show(vbox);
  gtk_container_add(GTK_CONTAINER(hpaned), vbox);

/*
 * The Toolbar
 */
  toolbar = gtk_toolbar_new();
  gtk_widget_show(toolbar);
  gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
  gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
  arg_add_value(ctrls, "TOOLBAR", ARG_PTR, -1, toolbar);

  icon = gtk_image_new_from_stock("gtk-help",
      gtk_toolbar_get_icon_size(GTK_TOOLBAR(toolbar)));
  toolbar_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
      GTK_TOOLBAR_CHILD_BUTTON, NULL,
      _("Scan Assistant"), _("Scan Assistant"),
      NULL, icon, GTK_SIGNAL_FUNC(prefs_scan_assistant), MainDialog);
  gtk_widget_show(toolbar_button);

  icon = gtk_image_new_from_stock("gtk-new",
      gtk_toolbar_get_icon_size(GTK_TOOLBAR(toolbar)));
  toolbar_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
      GTK_TOOLBAR_CHILD_BUTTON, NULL,
      _("New"), _("New"),
      NULL, icon, GTK_SIGNAL_FUNC(scopetree_context_new), NULL);
  gtk_widget_show(toolbar_button);

  icon = gtk_image_new_from_stock("gtk-delete",
      gtk_toolbar_get_icon_size(GTK_TOOLBAR(toolbar)));
  toolbar_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
      GTK_TOOLBAR_CHILD_BUTTON, NULL,
      _("Delete"), _("Delete"),
      NULL, icon, GTK_SIGNAL_FUNC(scopetree_context_delete), NULL);
  gtk_widget_show(toolbar_button);
  arg_add_value(ctrls, "DELETECONTEXT_BUTTON", ARG_PTR, -1, toolbar_button);

  gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));

  icon = gtk_image_new_from_stock("nessus-connect",
      gtk_toolbar_get_icon_size(GTK_TOOLBAR(toolbar)));
  toolbar_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
      GTK_TOOLBAR_CHILD_BUTTON, NULL,
      _("Connect"), _("Connect"),
      NULL, icon, GTK_SIGNAL_FUNC(prefs_dialog_auth_connect), MainDialog);
  gtk_widget_show(toolbar_button);
  arg_add_value(ctrls, "CONNECT_BUTTON", ARG_PTR, -1, toolbar_button);

  icon = gtk_image_new_from_stock("nessus-disconnect",
      gtk_toolbar_get_icon_size(GTK_TOOLBAR(toolbar)));
  toolbar_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
      GTK_TOOLBAR_CHILD_BUTTON, NULL,
      _("Disconnect"), _("Disconnect"),
      NULL, icon, GTK_SIGNAL_FUNC(prefs_dialog_auth_disconnect), MainDialog);
  gtk_widget_show(toolbar_button);
  arg_add_value(ctrls, "DISCONNECT_BUTTON", ARG_PTR, -1, toolbar_button);

  gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));

  icon = gtk_image_new_from_stock("gtk-execute",
      gtk_toolbar_get_icon_size(GTK_TOOLBAR(toolbar)));
  toolbar_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
      GTK_TOOLBAR_CHILD_BUTTON, NULL,
      _("Execute"), _("Execute"),
      NULL, icon, GTK_SIGNAL_FUNC(prefs_dialog_execute), ctrls);
  gtk_widget_show(toolbar_button);
  arg_add_value(ctrls, "EXECSCOPE_BUTTON", ARG_PTR, -1, toolbar_button);

#if 0
  icon = gtk_image_new_from_stock("gtk-stop",
      gtk_toolbar_get_icon_size(GTK_TOOLBAR(toolbar)));
  toolbar_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
      GTK_TOOLBAR_CHILD_BUTTON, NULL,
      _("Stop"), _("Stop"),
      NULL, icon, GTK_SIGNAL_FUNC(prefs_dialog_execute), NULL);
  gtk_widget_show(toolbar_button);
  gtk_widget_set_sensitive(toolbar_button, FALSE);
#endif

/*
 * The Scope Tree
 */

  prefs_scope_tree = prefs_dialog_scope_tree(context);
  frame = arg_get_value(prefs_scope_tree, "FRAME");
  gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
  arg_add_value(ctrls, "SCOPETREE", ARG_PTR, -1, prefs_scope_tree);

/*
 * The Context Frame
 */

  frame = gtk_frame_new(NULL);
  gtk_frame_set_label(GTK_FRAME(frame), _("Context"));
  gtk_widget_show(frame);
  gtk_container_add(GTK_CONTAINER(hpaned), frame);
  arg_add_value(ctrls, "CONTEXTFRAME", ARG_PTR, -1, frame);

/*
 * The Context Notebook
 */
  notebook = gtk_notebook_new();
  gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
  gtk_container_add(GTK_CONTAINER(frame), notebook);
  gtk_widget_show(notebook);
  arg_add_value(ctrls, "CONTEXTNOTEBOOK", ARG_PTR, -1, notebook);

/*
 * We set up the pages of our notebook
 */
  prefs_comment = prefs_dialog_comment();
  prefs_options = prefs_dialog_options(context, ctrls);
  prefs_report = prefs_dialog_report();

  arg_add_value(ctrls, "COMMENT", ARG_ARGLIST, -1, prefs_comment);
  arg_add_value(ctrls, "OPTIONS", ARG_ARGLIST, -1, prefs_options);
  arg_add_value(ctrls, "REPORT", ARG_ARGLIST, -1, prefs_report);

/*
 * and we append them to it
 */

  /* Tab "Comments" */
  label = gtk_label_new(_("Comments"));
  vbox = arg_get_value(prefs_comment, "VBOX");
  gtk_widget_show(vbox);
  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);

  /* Tab "Options" */
  label = gtk_label_new(_("Options"));
  vbox = arg_get_value(prefs_options, "VBOX");
  gtk_widget_show(vbox);
  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);

  /* Tab "Report" */
  label = gtk_label_new(_("Report"));
  vbox = arg_get_value(prefs_report, "VBOX");
  gtk_widget_show(vbox);
  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);

  g_signal_connect_after(G_OBJECT(notebook), "switch-page",
      G_CALLBACK(prefs_context_switch_notebookpage), NULL);

/*
 * Message Log
 */

  /* The frame */
  msglogframe = gtk_frame_new(NULL);
  gtk_widget_show(msglogframe);
  gtk_box_pack_start(GTK_BOX(box), msglogframe, TRUE, TRUE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(msglogframe), 4);
  arg_add_value(ctrls, "MSGLOGFRAME", ARG_PTR, -1, msglogframe);

  /* The label for the frame */
  label = gtk_label_new(_("Message log"));
  gtk_widget_show(label);
  gtk_frame_set_label_widget(GTK_FRAME(msglogframe), label);

  /* The scrolled window */
  scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
  gtk_widget_show(scrolledwindow);
  gtk_container_add(GTK_CONTAINER(msglogframe), scrolledwindow);
  gtk_container_set_border_width(GTK_CONTAINER(scrolledwindow), 4);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow),
      GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
  gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(scrolledwindow),
      GTK_CORNER_TOP_RIGHT);
  arg_add_value(ctrls, "MSGLOGSCROLL", ARG_PTR, -1, scrolledwindow);

  /* The text view */
  textview = gtk_text_view_new();
  gtk_widget_show(textview);
  gtk_container_add(GTK_CONTAINER(scrolledwindow), textview);
  gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE);
  gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)),
      _("Welcome to NessusClient, http://www.nessus.org/"
	"\nCopyright 1998-2005 by Renaud Deraison"
	"\nAuthors: Renaud Deraison, Thomas Arendsen Hein, Jan-Oliver Wagner"
	", Bernhard Herzog, Michel Arboi (SSL-Support), Bruce Verderaime (Pie/Charts)"
	"\n"),
      -1);
  arg_add_value(ctrls, "MSGLOGTEXT", ARG_PTR, -1, textview);

  /* The whole Message Log frame is invisible by default */
  gtk_widget_hide(msglogframe);


/*
 * Status bar
 */
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_widget_show(hbox);
  gtk_box_pack_end(GTK_BOX(box), hbox, FALSE, TRUE, 0);

  hpaned = gtk_hpaned_new();
  gtk_widget_show(hpaned);
  gtk_box_pack_start(GTK_BOX(hbox), hpaned, TRUE, TRUE, 1);

  statusbar = gtk_statusbar_new();
  gtk_widget_show(statusbar);
  gtk_paned_pack1(GTK_PANED(hpaned), statusbar, TRUE, FALSE);
  gtk_widget_set_size_request(statusbar, 200, -1);
  gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), FALSE);

  statusbar = gtk_statusbar_new();
  gtk_widget_show(statusbar);
  gtk_paned_pack2(GTK_PANED(hpaned), statusbar, TRUE, FALSE);
  gtk_widget_set_size_request(statusbar, 200, -1);
  gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), FALSE);
  arg_add_value(ctrls, "CONNECT_STATUSBAR", ARG_PTR, -1, statusbar);
  gtk_statusbar_push(GTK_STATUSBAR(statusbar),
      gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "connection"),
      _("not connected"));

  icon = gtk_image_new();
  gtk_widget_show(icon);
  gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, TRUE, 0);
  arg_add_value(ctrls, "CONNECT_ENCRYPTED_IMAGE", ARG_PTR, -1, icon);

/*
 * Final
 */
  menuitem = arg_get_value(ctrls, "TOGGLETOOLBAR_MENUITEM");
  gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
      !prefs_get_int(Global, "hide_toolbar"));
  toggle_toolbar(menuitem, ctrls);
  menuitem = arg_get_value(ctrls, "TOGGLEMSGLOG_MENUITEM");
  gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
      prefs_get_int(Global, "hide_msglog"));
  toggle_msglog(menuitem, ctrls);

  prefs_dialog_set_defaults(context, ctrls);
  prefs_dialog_set_tooltips(ctrls);
  gtk_widget_show(window);
}


void
prefs_dialog_set_defaults(context, ctrls)
  struct context *context;
  struct arglist *ctrls;
{
#define EX_NONE 1
#define EX_DNS 2
#define EX_IP 4
#define EX_NFS 8

  struct arglist *t, *serv;
  char *v;
  int flag = 0;
  GtkWidget *gtkw;


  serv = arg_get_value(context->prefs, "SERVER_PREFS");
  if(!serv)
    return;


  t = arg_get_value(ctrls, "PLUGINS");
  gtkw = arg_get_value(t, "ENABLE_DEPS_AT_RUNTIME");
  if(gtkw)
  {
    v = arg_get_value(serv, "auto_enable_dependencies");
    if(arg_get_type(serv, "auto_enable_dependencies") == ARG_INT)
    {
      char *s = strdup(v ? "yes" : "no");

      arg_set_type(serv, "auto_enable_dependencies", ARG_STRING);
      arg_set_value(serv, "auto_enable_dependencies", strlen(s), s);
      v = s;
    }
    if(v && !strcmp(v, "yes"))
      GTK_TOGGLE_BUTTON(gtkw)->active = TRUE;
    else
      GTK_TOGGLE_BUTTON(gtkw)->active = FALSE;
  }
  gtkw = arg_get_value(t, "SILENT_DEPS");
  if(gtkw)
  {
    v = arg_get_value(serv, "silent_dependencies");
    if(arg_get_type(serv, "silent_dependencies") == ARG_INT)
    {
      char *s = strdup(v ? "yes" : "no");

      arg_set_type(serv, "silent_dependencies", ARG_STRING);
      arg_set_value(serv, "silent_dependencies", strlen(s), s);
      v = s;
    }
    if(v && !strcmp(v, "yes"))
      GTK_TOGGLE_BUTTON(gtkw)->active = TRUE;
    else
      GTK_TOGGLE_BUTTON(gtkw)->active = FALSE;
  }
  /*
   *  Host expansion options
   */
  t = arg_get_value(ctrls, "TARGET");
  gtk_entry_set_text(GTK_ENTRY(arg_get_value(t, "TARGET")),
      prefs_get_string(context, "targets"));
  v = arg_get_value(serv, "host_expansion");
  if(!v)
    flag |= EX_NONE;
  else
  {
    if(strstr(v, "dns"))
      flag = EX_DNS;
    if(strstr(v, "nfs"))
      flag |= EX_NFS;
    if(strstr(v, "none"))
      flag |= EX_NONE;
    if(strstr(v, "ip"))
      flag |= EX_IP;
  }

  if(!(flag & EX_NONE))
  {
    GtkWidget *w;

    w = arg_get_value(t, "DNS_EXPAND");
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(w), (flag & EX_DNS));
  }

  /*
   * Scan options 
   */
  t = arg_get_value(ctrls, "SCAN_OPTIONS");
  gtkw = arg_get_value(t, "PING_HOSTS");
  v = arg_get_value(serv, "ping_hosts");
  if(arg_get_type(serv, "ping_hosts") == ARG_INT)
  {
    char *s = emalloc(4);

    if(v)
      strncpy(s, "yes", 3);
    else
      strncpy(s, "no", 2);

    arg_set_value(serv, "ping_hosts", strlen(s), s);
    arg_set_type(serv, "ping_hosts", ARG_STRING);
  }
  v = arg_get_value(serv, "ping_hosts");
  if(v)
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), !strcmp(v, "yes"));

  gtkw = arg_get_value(t, "REVERSE_LOOKUP");
  v = arg_get_value(serv, "reverse_lookup");
  if(arg_get_type(serv, "reverse_lookup") == ARG_INT)
  {
    char *s = emalloc(4);

    if(v)
      strncpy(s, "yes", 3);
    else
      strncpy(s, "no", 2);

    arg_set_value(serv, "reverse_lookup", strlen(s), s);
    arg_set_type(serv, "reverse_lookup", ARG_STRING);
  }
  v = arg_get_value(serv, "reverse_lookup");
  if(v)
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), !strcmp(v, "yes"));


  gtkw = arg_get_value(t, "OPTIMIZE_TEST");
  v = arg_get_value(serv, "optimize_test");
  if(arg_get_type(serv, "optimize_test") == ARG_INT)
  {
    char *s = emalloc(4);

    if(v)
      strncpy(s, "yes", 3);
    else
      strncpy(s, "no", 2);

    arg_set_value(serv, "optimize_test", strlen(s), s);
    arg_set_type(serv, "optimize_test", ARG_STRING);
  }
  v = arg_get_value(serv, "optimize_test");
  if(v)
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), !strcmp(v, "yes"));
  else
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), 1);


  gtkw = arg_get_value(t, "SAFE_CHECKS");
  v = arg_get_value(serv, "safe_checks");
  if(arg_get_type(serv, "safe_checks") == ARG_INT)
  {
    char *s = emalloc(4);

    if(v)
      strncpy(s, "yes", 3);
    else
      strncpy(s, "no", 2);

    arg_set_value(serv, "safe_checks", strlen(s), s);
    arg_set_type(serv, "safe_checks", ARG_STRING);
  }

  v = arg_get_value(serv, "safe_checks");
  if(v)
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), !strcmp(v, "yes"));
  else
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), 1);


  gtkw = arg_get_value(t, "USE_MAC_ADDR");
  v = arg_get_value(serv, "use_mac_addr");
  if(arg_get_type(serv, "use_mac_addr") == ARG_INT)
  {
    char *s = emalloc(4);

    if(v)
      strncpy(s, "yes", 3);
    else
      strncpy(s, "no", 2);

    arg_set_value(serv, "use_mac_addr", strlen(s), s);
    arg_set_type(serv, "use_mac_addr", ARG_STRING);
  }

  v = arg_get_value(serv, "use_mac_addr");
  if(v)
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), !strcmp(v, "yes"));
  else
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), 0);

  v = arg_get_value(serv, "port_range");
  if(v)
  {
    gtkw = arg_get_value(t, "PORT_RANGE");
    if(gtkw)
      gtk_entry_set_text(GTK_ENTRY(gtkw), v);
  }

  gtkw = arg_get_value(t, "UNSCANNED_CLOSED");
  v = arg_get_value(serv, "unscanned_closed");
  if(arg_get_type(serv, "unscanned_closed") == ARG_INT)
  {

    char *s;
    int v;

    v = (int)arg_get_value(serv, "unscanned_closed");
    if(v)
      s = strdup("yes");
    else
      s = strdup("no");

    arg_set_value(serv, "unscanned_closed", strlen(s), s);
    arg_set_type(serv, "unscanned_closed", ARG_STRING);
  }
  v = arg_get_value(serv, "unscanned_closed");

  if(v)
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), !strcmp(v, "yes"));
  else
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(gtkw), 0);



  gtkw = arg_get_value(t, "MAX_HOSTS");
  if(gtkw)
  {
    v = arg_get_value(serv, "max_hosts");
    if(v)
      gtk_entry_set_text(GTK_ENTRY(gtkw), v);
  }

  gtkw = arg_get_value(t, "MAX_CHECKS");
  if(gtkw)
  {
    v = arg_get_value(serv, "max_checks");
    if(v)
      gtk_entry_set_text(GTK_ENTRY(gtkw), v);
  }

  gtkw = arg_get_value(t, "CGI_PATH");
  if(gtkw)
  {
    v = arg_get_value(serv, "cgi_path");
    if(v)
      gtk_entry_set_text(GTK_ENTRY(gtkw), v);
  }

  /*
   * User
   */

  t = arg_get_value(ctrls, "USER");

  gtkw = arg_get_value(t, "RULES");
  if(gtkw)
  {
    GtkWidget *item;
    GtkWidget *label;

    GList *dlist = NULL;
    GList *oldlist = (void *)arg_get_value(t, "RULES_DLIST");
    struct arglist *rules = arg_get_value(context->prefs, "RULES");

    if(oldlist)
      gtk_list_remove_items(GTK_LIST(gtkw), oldlist);

    while(rules && rules->next)
    {
      GtkWidget *box;

      if(strlen(rules->value))
      {
	item = gtk_list_item_new();
	gtk_object_set_data(GTK_OBJECT(item), "rule", rules->name);
	box = gtk_hbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(item), box);
	gtk_widget_show(box);
	label = gtk_label_new(rules->value);
	gtk_widget_show(label);
	gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
	dlist = g_list_append(dlist, item);
	rules = rules->next;
	gtk_widget_show(item);
      }
    }
    if(arg_get_value(t, "RULES_DLIST"))
      arg_set_value(t, "RULES_DLIST", -1, dlist);
    else
      arg_add_value(t, "RULES_DLIST", ARG_PTR, -1, dlist);
    gtk_list_append_items(GTK_LIST(gtkw), dlist);
  }

#ifdef ENABLE_SAVE_KB
  prefs_dialog_kb_set_prefs(arg_get_value(ctrls, "SAVE_KB"), context->prefs);
#endif
}


static void
prefs_dialog_set_tooltips(ctrls)
  struct arglist *ctrls;
{
  struct arglist *t;
  GtkTooltips *tooltips;
  GtkWidget *w;

  tooltips = gtk_tooltips_new();
  arg_add_value(ctrls, "TOOLTIPS", ARG_PTR, -1, tooltips);

  t = arg_get_value(ctrls, "PLUGINS");
  w = arg_get_value(t, "ENABLE_DEPS_AT_RUNTIME");
  gtk_tooltips_set_tip(tooltips, w, HLP_ENABLE_DEPS_AT_RUNTIME, "");

  w = arg_get_value(t, "SILENT_DEPS");
  gtk_tooltips_set_tip(tooltips, w, HLP_SILENT_DEPS, "");

  t = arg_get_value(ctrls, "TARGET");
  w = arg_get_value(t, "DNS_EXPAND");
  gtk_tooltips_set_tip(tooltips, w, HLP_HOST_EXPANSION_DNS, "");

  w = arg_get_value(t, "TARGET");
  gtk_tooltips_set_tip(tooltips, w, HLP_TARGET_PRIMARY_TARGET, "");

  w = arg_get_value(t, "READ_FROM_FILE");
  gtk_tooltips_set_tip(tooltips, w, HLP_TARGET_READ_FROM_FILE, "");


  t = arg_get_value(ctrls, "SCAN_OPTIONS");
  w = arg_get_value(t, "PING_HOSTS");
  gtk_tooltips_set_tip(tooltips, w, HLP_SCAN_OPT_PING, "");
  w = arg_get_value(t, "OPTIMIZE_TEST");
  gtk_tooltips_set_tip(tooltips, w, HLP_SCAN_OPT_OPTIMIZE, "");

  w = arg_get_value(t, "SAFE_CHECKS");
  gtk_tooltips_set_tip(tooltips, w, HLP_SCAN_OPT_SAFE_CHECKS, "");

  w = arg_get_value(t, "USE_MAC_ADDR");
  gtk_tooltips_set_tip(tooltips, w, HLP_SCAN_OPT_USE_MAC_ADDR, "");

  w = arg_get_value(t, "REVERSE_LOOKUP");
  gtk_tooltips_set_tip(tooltips, w, HLP_SCAN_OPT_REVERSE_LOOKUP, "");
  w = arg_get_value(t, "PORT_RANGE");
  gtk_tooltips_set_tip(tooltips, w, HLP_SCAN_OPT_PORT_RANGE, "");
  w = arg_get_value(t, "UNSCANNED_CLOSED");
  gtk_tooltips_set_tip(tooltips, w, HLP_UNSCANNED_CLOSED, "");

  w = arg_get_value(t, "MAX_HOSTS");
  gtk_tooltips_set_tip(tooltips, w, HLP_MISC_MAX_HOSTS, "");
  w = arg_get_value(t, "MAX_CHECKS");
  gtk_tooltips_set_tip(tooltips, w, HLP_MISC_MAX_CHECKS, "");
  w = arg_get_value(t, "CGI_PATH");
  gtk_tooltips_set_tip(tooltips, w, HLP_CGI_PATH, "");
  t = arg_get_value(ctrls, "USER");
  gtk_tooltips_enable(tooltips);
}


void
prefs_dialog_apply(context, ctrls)
  struct context *context;
  struct arglist *ctrls;
{
  struct arglist *prefs;
  struct arglist *serv;
  struct arglist *t;
  char expansion[30];
  char *s;
  GtkWidget *gtkw;

  /* Save comment to preferences */
  store_comment(context, arg_get_value(ctrls, "COMMENT"));

  if(context->type == CONTEXT_TASK || context->type == CONTEXT_REPORT)
    return;

  /*
   * FIXME:
   * Only try to save values if GTK widgets were changed.
   * Otherwise prefs_dialog_set_defaults can't set default
   * values from server.
   */

  bzero(expansion, 30);
  prefs = context->prefs;
  serv = arg_get_value(prefs, "SERVER_PREFS");
  if(!serv)
  {
    serv = emalloc(sizeof(struct arglist));
    arg_add_value(prefs, "SERVER_PREFS", ARG_ARGLIST, -1, serv);
  }


  t = arg_get_value(ctrls, "PLUGINS");
  gtkw = arg_get_value(t, "ENABLE_DEPS_AT_RUNTIME");
  if(gtkw)
  {
    char *s;

    if(GTK_TOGGLE_BUTTON(gtkw)->active)
      s = estrdup("yes");
    else
      s = estrdup("no");

    if(arg_get_value(serv, "auto_enable_dependencies"))
      arg_set_value(serv, "auto_enable_dependencies", strlen(s), s);
    else
      arg_add_value(serv, "auto_enable_dependencies", ARG_STRING, strlen(s),
	  s);
  }
  gtkw = arg_get_value(t, "SILENT_DEPS");
  if(gtkw)
  {
    char *s;

    if(GTK_TOGGLE_BUTTON(gtkw)->active)
      s = estrdup("yes");
    else
      s = estrdup("no");

    if(arg_get_value(serv, "silent_dependencies"))
      arg_set_value(serv, "silent_dependencies", strlen(s), s);
    else
      arg_add_value(serv, "silent_dependencies", ARG_STRING, strlen(s), s);
  }




  /*
   * Host expansion
   */
  t = arg_get_value(ctrls, "TARGET");
  gtkw = arg_get_value(t, "DNS_EXPAND");
  if(GTK_TOGGLE_BUTTON(gtkw)->active)
    strcat(expansion, "dns;");

  strcat(expansion, "ip;");

  if(!strlen(expansion))
    strncpy(expansion, "none;", 5);
  expansion[strlen(expansion) - 1] = 0;

  s = (char *)gtk_entry_get_text(GTK_ENTRY(arg_get_value(t, "TARGET")));
  prefs_set_string(context, "targets", s);

  s = emalloc(strlen(expansion) + 1);
  strncpy(s, expansion, strlen(expansion));

  if(arg_get_value(serv, "host_expansion"))
    arg_set_value(serv, "host_expansion", strlen(s), s);
  else
    arg_add_value(serv, "host_expansion", ARG_STRING, strlen(s), s);




  /*
   * Scan options
   */

  t = arg_get_value(ctrls, "SCAN_OPTIONS");
  gtkw = arg_get_value(t, "PING_HOSTS");
  s = emalloc(4);

  if(GTK_TOGGLE_BUTTON(gtkw)->active)
    strncpy(s, "yes", 3);
  else
    strncpy(s, "no", 4);

  if(arg_get_value(serv, "ping_hosts"))
    arg_set_value(serv, "ping_hosts", strlen(s), s);
  else
    arg_add_value(serv, "ping_hosts", ARG_STRING, strlen(s), s);


  gtkw = arg_get_value(t, "REVERSE_LOOKUP");
  s = emalloc(4);
  if(GTK_TOGGLE_BUTTON(gtkw)->active)
    strncpy(s, "yes", 3);
  else
    strncpy(s, "no", 4);

  if(arg_get_value(serv, "reverse_lookup"))
    arg_set_value(serv, "reverse_lookup", strlen(s), s);
  else
    arg_add_value(serv, "reverse_lookup", ARG_STRING, strlen(s), s);

  gtkw = arg_get_value(t, "OPTIMIZE_TEST");
  s = emalloc(4);
  if(GTK_TOGGLE_BUTTON(gtkw)->active)
    strncpy(s, "yes", 3);
  else
    strncpy(s, "no", 4);

  if(arg_get_value(serv, "optimize_test"))
    arg_set_value(serv, "optimize_test", strlen(s), s);
  else
    arg_add_value(serv, "optimize_test", ARG_STRING, strlen(s), s);


  gtkw = arg_get_value(t, "SAFE_CHECKS");
  s = emalloc(4);
  if(GTK_TOGGLE_BUTTON(gtkw)->active)
    strncpy(s, "yes", 3);
  else
    strncpy(s, "no", 4);

  if(arg_get_value(serv, "safe_checks"))
    arg_set_value(serv, "safe_checks", strlen(s), s);
  else
    arg_add_value(serv, "safe_checks", ARG_STRING, strlen(s), s);


  gtkw = arg_get_value(t, "USE_MAC_ADDR");
  s = emalloc(4);
  if(GTK_TOGGLE_BUTTON(gtkw)->active)
    strncpy(s, "yes", 3);
  else
    strncpy(s, "no", 4);

  if(arg_get_value(serv, "use_mac_addr"))
    arg_set_value(serv, "use_mac_addr", strlen(s), s);
  else
    arg_add_value(serv, "use_mac_addr", ARG_STRING, strlen(s), s);


  t = arg_get_value(ctrls, "SCAN_OPTIONS");
  gtkw = arg_get_value(t, "PORT_RANGE");
  s = emalloc(strlen(gtk_entry_get_text(GTK_ENTRY(gtkw))) + 1);
  strncpy(s, gtk_entry_get_text(GTK_ENTRY(gtkw)),
      strlen(gtk_entry_get_text(GTK_ENTRY(gtkw))));

  if(arg_get_value(serv, "port_range"))
    arg_set_value(serv, "port_range", strlen(s), s);
  else
    arg_add_value(serv, "port_range", ARG_STRING, strlen(s), s);


  gtkw = arg_get_value(t, "UNSCANNED_CLOSED");
  s = emalloc(4);
  if(GTK_TOGGLE_BUTTON(gtkw)->active)
    strncpy(s, "yes", 3);
  else
    strncpy(s, "no", 4);

  if(arg_get_value(serv, "unscanned_closed"))
    arg_set_value(serv, "unscanned_closed", strlen(s), s);
  else
    arg_add_value(serv, "unscanned_closed", ARG_STRING, strlen(s), s);


  gtkw = arg_get_value(t, "MAX_HOSTS");

  s = emalloc(strlen(gtk_entry_get_text(GTK_ENTRY(gtkw))) + 1);

  strncpy(s, gtk_entry_get_text(GTK_ENTRY(gtkw)),
      strlen(gtk_entry_get_text(GTK_ENTRY(gtkw))));

  if(arg_get_value(serv, "max_hosts"))
    arg_set_value(serv, "max_hosts", strlen(s), s);
  else
    arg_add_value(serv, "max_hosts", ARG_STRING, strlen(s), s);


  gtkw = arg_get_value(t, "MAX_CHECKS");

  s = emalloc(strlen(gtk_entry_get_text(GTK_ENTRY(gtkw))) + 1);

  strncpy(s, gtk_entry_get_text(GTK_ENTRY(gtkw)),
      strlen(gtk_entry_get_text(GTK_ENTRY(gtkw))));

  if(arg_get_value(serv, "max_checks"))
    arg_set_value(serv, "max_checks", strlen(s), s);
  else
    arg_add_value(serv, "max_checks", ARG_STRING, strlen(s), s);


  gtkw = arg_get_value(t, "CGI_PATH");
  s = estrdup((char *)gtk_entry_get_text(GTK_ENTRY(gtkw)));


  if(arg_get_value(serv, "cgi_path"))
    arg_set_value(serv, "cgi_path", strlen(s), s);
  else
    arg_add_value(serv, "cgi_path", ARG_STRING, strlen(s), s);

#ifdef ENABLE_SAVE_KB
  t = arg_get_value(ctrls, "SAVE_KB");
  prefs_dialog_kb_get_prefs(context, t);
#endif


  /*
   * Client-side User Access Rules
   * Get them out of the USRER->RULES_TREE and push them into
   * context->prefs->CLIENTSIDE_USERRULES
   */
  t = arg_get_value(ctrls, "USER");
  gtkw = arg_get_value(t, "RULES_TREE");
  if (gtkw)
  {
    GtkTreeModel * store;
    GtkTreePath * path;
    GtkTreeIter iter;
    int n = 0;
    char * rule, * name = NULL;
    struct arglist * clientside_userrules;

    /* first of all, remove the old stuff */
    clientside_userrules = emalloc(sizeof(struct arglist));
    if (arg_get_value(prefs, "CLIENTSIDE_USERRULES"))
    {
      arg_free_all(arg_get_value(prefs, "CLIENTSIDE_USERRULES"));
      arg_set_value(prefs, "CLIENTSIDE_USERRULES", -1, clientside_userrules);
    } else
      arg_add_value(prefs, "CLIENTSIDE_USERRULES", ARG_ARGLIST, -1,
                    clientside_userrules);

    store = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkw));

    /* go to the third entry */
    path = gtk_tree_path_new_from_string("2:0");
    if (gtk_tree_model_get_iter(store, &iter, path))
    {
      do {
        gtk_tree_model_get(store, &iter, 0, &rule, -1);

        name = emalloc(20);
        sprintf(name, "%d", n);
        arg_add_value(clientside_userrules, name, ARG_STRING,
                      strlen(rule), rule);
        n ++;
      } while (gtk_tree_model_iter_next(store, &iter));
    }
  }
}


/* XXX Warning:
 * saves to context->plugins and context->scanners,
 * NOT to context->prefs["PLUGINS_PREFS"]
 */
void
prefs_dialog_apply_plugin_prefs(plugins)
  struct nessus_plugin *plugins;
{
  while(plugins!= NULL )
  {
    struct arglist *pref;
    char *type;
    char *value;

    if((pref = plugins->plugin_prefs) != NULL )
      while(pref && pref->next)
      {
	if((type = (char *)arg_get_value(pref->value, "type")))
	{
	  if(!strcmp(type, PREF_ENTRY) ||
	      !strcmp(type, PREF_FILE) || !strcmp(type, PREF_PASSWORD))
	  {
	    GtkWidget *entry = arg_get_value(pref->value, "ENTRY");

	    if(entry)
	    {
	      value = (char *)gtk_entry_get_text(GTK_ENTRY(entry));
	      arg_set_value(pref->value, "value", strlen(value),
		  estrdup(value));
	    }
	  }
	  else if(!strcmp(type, PREF_CHECKBOX))
	  {
	    GtkWidget *button = arg_get_value(pref->value, "CHECKBOX");

	    if(button)
	    {
	      char *value =
		  GTK_TOGGLE_BUTTON(button)->active ? "yes" : "no";
	      arg_set_value(pref->value, "value", strlen(value),
		  estrdup(value));
	    }
	  }
	  else if(!strcmp(type, PREF_RADIO))
	  {
        GSList *list = NULL;
        char * value = NULL;

        list = arg_get_value(pref->value, "RADIOBUTTONS");

        if (list)
        {
          /* First pass: find the active entry */
          while (list)
          {
            GtkWidget *button = list->data;

            if (GTK_TOGGLE_BUTTON(button)->active)
            {
              value = estrdup(gtk_object_get_data(GTK_OBJECT(button), "name"));
              break;
            }
            list = list->next;
          }
          /* Second pass: find all other entries and append
           * them separated with ";" */
          list = arg_get_value(pref->value, "RADIOBUTTONS");
          while (list)
          {
            GtkWidget *button = list->data;

            if (! GTK_TOGGLE_BUTTON(button)->active)
            {
              char * v = gtk_object_get_data(GTK_OBJECT(button), "name");
              value = (char *) erealloc((void *)value, (size_t) (strlen(value) + strlen(";") + strlen(v) + 1));
              strcat(value, ";");
              strcat(value, v);
            }
            list = list->next;
          }
        }
        if(value)
          arg_set_value(pref->value, "value", strlen(value), value);
	  }
	}
	pref = pref->next;
      }
    plugins = plugins->next;
  }
}


int
prefs_dialog_execute(w, ctrls)
  GtkWidget *w;
  struct arglist *ctrls;
{
  struct context *context = context_by_type(Context, CONTEXT_SCOPE);
  char *hostname;

  prefs_context_update(context);
  prefs_dialog_apply(context, ctrls);
  prefs_dialog_apply_plugin_prefs(context->plugins);
  prefs_dialog_apply_plugin_prefs(context->scanners);
  context_sync_plugin_prefs(context);

  /*
   * Check for the errors
   */

  if(!prefs_dialog_auth_connection(context))
    return (0);

  /* if the target is a file, then translate it */
  hostname = target_translate(prefs_get_string(context, "targets"));

  if(hostname == NULL || hostname[0] == '\0')
  {
    show_error(_("You must enter the name of the primary target\n\
to attack in the 'target' section"));
    return (0);
  }

  monitor_dialog_setup(hostname, context);

  return (0);
}
#endif
