/* 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 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 <includes.h>
#include <gtk/gtk.h>

#include "../xstuff.h"
#include "../plugin_infos.h"
#include "../families.h"
#include "../preferences.h"
#include "globals.h"

static struct plugin_families * families;

void prefs_plugins_redraw(GtkWidget *, void *, struct arglist *);
static void fill_plugins_family(struct arglist *);
static void prefs_family_toggle_callback(GtkWidget * , struct arglist *);
static void prefs_plugin_list_toggle_callback(GtkWidget * , struct arglist * );
static void prefs_plugin_list_callback(GtkWidget * , struct arglist * );
static void prefs_family_list_callback(GtkWidget * , struct arglist * );


/*
 * plugin_list_setup
 *
 * Draws the main window showing informations
 * about the plugins of the server
 */
struct arglist *  
prefs_dialog_plugins()
{
  struct arglist * ctrls = emalloc(sizeof(struct arglist));
  GtkWidget * frame;
  GtkWidget * families_window;
  GtkWidget * plugins_window;
  GtkWidget * w_box;
  GtkWidget * list;
 
 
 
  frame = gtk_frame_new("Plugin selection");
  gtk_container_border_width(GTK_CONTAINER(frame), 10);
  arg_add_value(ctrls, "FRAME", ARG_PTR, -1, frame);
  
  w_box = gtk_vbox_new(TRUE, 5);
  gtk_container_add(GTK_CONTAINER(frame), w_box);
  
  gtk_container_border_width(GTK_CONTAINER(w_box), 5);
  
  families_window = gtk_scrolled_window_new(NULL,NULL);
  gtk_container_border_width(GTK_CONTAINER(families_window), 10);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(families_window),
				 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_widget_set_usize(families_window, 300, 130);
  gtk_box_pack_start(GTK_BOX(w_box), families_window, TRUE, TRUE, 0);
  
  plugins_window = gtk_scrolled_window_new(NULL,NULL);
  gtk_container_border_width(GTK_CONTAINER(plugins_window), 10);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(plugins_window),
				 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_widget_set_usize(plugins_window, 300, 130);
  gtk_box_pack_start(GTK_BOX(w_box), plugins_window, TRUE, TRUE, 0);
  
  
  list = gtk_list_new();
  arg_add_value(ctrls, "FAMILIES_LIST", ARG_PTR, -1, list);
  gtk_container_add(GTK_CONTAINER(families_window),list);
  gtk_widget_show(list);
  
  gtk_signal_connect(GTK_OBJECT(list),
		     "selection_changed",
		     GTK_SIGNAL_FUNC(prefs_family_list_callback),
		     ctrls);
  
  list = gtk_list_new();                          
  arg_add_value(ctrls, "PLUGINS_LIST", ARG_PTR, -1, list);
  gtk_container_add(GTK_CONTAINER(plugins_window), list);
  gtk_widget_show(list);
  gtk_signal_connect(GTK_OBJECT(list),
		     "selection_changed",
		     GTK_SIGNAL_FUNC(prefs_plugin_list_callback),     
		     ctrls);   
 arg_add_value(ctrls, "FAMILIES", ARG_PTR, -1, families);                   
 fill_plugins_family(ctrls);
 gtk_widget_show(families_window);
 gtk_widget_show(plugins_window);
 gtk_widget_show(w_box);
 gtk_widget_show(frame);
 arg_add_value(ctrls, "PLUGINS_NUM", ARG_INT, sizeof(int), (void *)PluginsNum);
 return(ctrls);
}



static void 
prefs_plugin_list_callback(widget, ctrls)
     GtkWidget * widget;
     struct arglist * ctrls;
{
  GtkObject * list_item;
  char * cur_plug;
  GList * dlist;
  GtkWidget * list = arg_get_value(ctrls, "PLUGINS_LIST");
  dlist = GTK_LIST(list)->selection;
  if(!dlist)return;
  
  list_item = GTK_OBJECT(dlist->data);
  cur_plug = gtk_object_get_data(list_item,"list_item_data");
  plugin_info_window_setup(Plugins, cur_plug);             
}

static void 
prefs_family_toggle_callback(w, ctrls)
     GtkWidget * w;
     struct arglist * ctrls;
{
  int enable = GTK_TOGGLE_BUTTON (w)->active;
  GList * dlist = NULL;
  GtkObject * list_item;
  GtkObject * button;
  struct arglist * plugin;
  char * name;
  GtkWidget * item;
  int check_manually = 1;
  
  item = w->parent->parent;
  list_item = GTK_OBJECT(item);
  name = gtk_object_get_data(list_item,"list_item_data");
  dlist = GTK_LIST(arg_get_value(ctrls, "PLUGINS_LIST"))->children;
  if(dlist)
    {
      list_item = GTK_OBJECT(dlist->data);
      
      plugin = gtk_object_get_data(list_item,"plugin");
      if(plug_get_family(plugin) && 
	 !strcmp(plug_get_family(plugin), name))
	{
          check_manually = 0;
	  while(dlist)
	    {
	      list_item = GTK_OBJECT(dlist->data);
	      button = gtk_object_get_data(list_item,"button");
	      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), enable);
	      dlist = dlist->next;
	    }
	}
    }
 if(check_manually)family_enable(name, Plugins, enable);
 pluginset_reload(Plugins, Scanners);
}

static 
void prefs_plugin_list_toggle_callback(w, plugin)
     GtkWidget * w;
     struct arglist * plugin;
{
  int state = (int)plug_get_launch(plugin);
  plug_set_launch(plugin,!state);
  pluginset_reload(Plugins, Scanners);
}

static
void 
prefs_family_list_callback(widget, ctrls)
     GtkWidget * widget; 
     struct arglist * ctrls;
{
  GList * dlist;
  GtkObject * list_item;
  char * cur_family;
  struct arglist * plugs = Plugins;
  GtkTooltips * tooltips;
  
  dlist = GTK_LIST(arg_get_value(ctrls, "FAMILIES_LIST"))->selection;
  if(!dlist)return;
  
  list_item = GTK_OBJECT(dlist->data);
  cur_family = gtk_object_get_data(list_item,"list_item_data");
  dlist = GTK_LIST(arg_get_value(ctrls, "PLUGINS_LIST"))->children;
  if(dlist)gtk_list_remove_items(GTK_LIST(arg_get_value(ctrls, "PLUGINS_LIST")),dlist); 
  dlist = NULL;
  tooltips = gtk_tooltips_new();
  while(plugs && plugs->next)
    {
      GtkWidget * item;
      GtkWidget * box;
      GtkWidget * button;
      GtkWidget * label;
      
      
      if(plug_get_family(plugs->value) &&
	 !strcmp(plug_get_family(plugs->value), cur_family))
	{
	  
	  item = gtk_list_item_new();
	  button = gtk_toggle_button_new_with_label(" ");
	  gtk_widget_set_usize(button, 15, 15);
	  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), 
				      (int)plug_get_launch(plugs->value));
	  
	  label = gtk_label_new(plugs->name);
	  box = gtk_hbox_new(FALSE,5);
	  gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
	  gtk_widget_show(label);
	  
	  gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE,0);
	  gtk_container_add(GTK_CONTAINER(item), box);
	  gtk_signal_connect(GTK_OBJECT(button),
			     "clicked",
			     GTK_SIGNAL_FUNC(prefs_plugin_list_toggle_callback),
			     plugs->value);
	  gtk_widget_show(button);
	  gtk_widget_show(box);
	  gtk_widget_show(item);
	  if(arg_get_value(plugs->value, "SUMMARY"))
	    gtk_tooltips_set_tip(tooltips, item, 
				 (gchar *)arg_get_value(plugs->value, "SUMMARY"),"");
	  dlist = g_list_append(dlist, item);
	  gtk_object_set_data(GTK_OBJECT(item),
			      "list_item_data",
			      plugs->name);
	  gtk_object_set_data(GTK_OBJECT(item),
			      "button",
			      button);     
	  gtk_object_set_data(GTK_OBJECT(item),
			      "plugin",
			      plugs->value);                                        
	}                    
      plugs = plugs->next;	
    }
  gtk_tooltips_enable(tooltips);
  gtk_list_append_items(GTK_LIST(arg_get_value(ctrls, "PLUGINS_LIST")), dlist);
  pluginset_reload(Plugins, Scanners);
}


void prefs_plugins_redraw(w, dumb, ctrls)
 GtkWidget * w;
 void * dumb;
 struct arglist * ctrls;
{
 int num;
 
 num = (int)arg_get_value(ctrls, "PLUGINS_NUM");
 if(num != PluginsNum){
  fill_plugins_family(ctrls);
  arg_set_value(ctrls, "PLUGINS_NUM", sizeof(int), (void *)PluginsNum);
  }
}


static void 
fill_plugins_family(ctrls)
 struct arglist * ctrls;
{
 GtkTooltips * tooltips;
 struct arglist * plugs = Plugins;
 struct plugin_families * lfamilies, *f;
 GList * dlist = NULL;
 
 lfamilies = families = family_init();
 while(plugs && plugs->next)
    {
      family_add(families, plugs->value);
      plugs = plugs->next;
    }
  plugs = Plugins;
  
 tooltips = gtk_tooltips_new();
 while(lfamilies && lfamilies->next)
   {
     GtkWidget * item;
     GtkWidget * box;
     GtkWidget * button;
     GtkWidget * label;
     struct plugin_families * old = arg_get_value(ctrls, "FAMILIES");
     int flag = 0;
     while(old && old->next && !flag)
     {
      if(old->name)flag = !strcmp(old->name, lfamilies->name);
      old = old->next;
     }
     if(flag)continue;
     item = gtk_list_item_new();
     
     button = gtk_toggle_button_new_with_label(" ");
     gtk_widget_set_usize(button, 15, 15);
     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), 
				 family_enabled(lfamilies->name, Plugins) ? TRUE:FALSE);
     label = gtk_label_new(lfamilies->name);
     box = gtk_hbox_new(FALSE,5);
     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
     gtk_widget_show(label);
     gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE,0);
	
     gtk_container_add(GTK_CONTAINER(item), box);
     gtk_signal_connect(GTK_OBJECT(button),
			"clicked",
			GTK_SIGNAL_FUNC(prefs_family_toggle_callback),
			ctrls);
     
     gtk_widget_show(button);
     gtk_widget_show(box);
     gtk_widget_show(item);
     dlist = g_list_append(dlist, item);
     gtk_object_set_data(GTK_OBJECT(item),
			 "list_item_data",
			 lfamilies->name);
     lfamilies = lfamilies->next;
   }
   gtk_tooltips_enable(tooltips);
   gtk_list_append_items(GTK_LIST(arg_get_value(ctrls, "FAMILIES_LIST")), dlist);
   f = arg_get_value(ctrls, "FAMILIES");
   arg_set_value(ctrls, "FAMILIES", -1, families);
   while(f && f->next)
   {
    struct plugin_families * prev;
    efree(&f->name);
    prev = f;
    f = f->next;
    efree(&prev);
   }
}
