/* Nessus
 * Copyright (C) 1998 - 2001 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"
#include "globals.h"
#ifdef USE_GTK
#ifdef HAVE_REGEX_SUPPORT
#include <regex.h>
#else
#include "nessus_regex.h"
#endif
#include "error_dlg.h"

#include <gtk/gtk.h>
#include "filter.h"

/* Default values, filter on name only. Memorize, so that when dialog is opened
   the same values are selected. */
static int filter_on_name = 1;
static int filter_on_description = 0;
static int filter_on_summary = 0;
static int filter_on_author = 0;
static int filter_on_id = 0;
static int filter_on_category = 0;
static int filter_on_cve = 0;
static int filter_on_bid = 0;
static int filter_on_xref = 0;


static struct arglist *
build_filter_dlog()
{
  GtkWindow * window = GTK_WINDOW(arg_get_value(MainDialog, "WINDOW"));
  GtkWidget * dialog;
  GtkWidget * label, *sep, * button, *entry;
  GtkWidget * box, *hbox, *frame,*vbox;
  struct arglist * ctrls = emalloc(sizeof(struct arglist));

  dialog = gtk_dialog_new_with_buttons(_("Filter plugins..."), window,
             GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
             GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
  gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
  gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);

  arg_add_value(ctrls, "WINDOW", ARG_PTR, -1, dialog);

  /* The overall vbox */
  box = GTK_DIALOG(dialog)->vbox;

 label = gtk_label_new(_("Filter plugins..."));
 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 1);
 gtk_widget_show(label);
 sep = gtk_hseparator_new();
 gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0);
 gtk_widget_show(sep);
 sep = gtk_hseparator_new();
 gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0);
 gtk_widget_show(sep);

 hbox = gtk_hbox_new(FALSE, FALSE);
 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 3);
 label = gtk_label_new(_("Pattern:"));
 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 6);
 gtk_widget_show(label);

 entry = gtk_entry_new();
 arg_add_value(ctrls, "ENTRY", ARG_PTR, -1, entry);
 gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 6);
 gtk_widget_show(entry);
 gtk_widget_show(hbox);

 frame = gtk_frame_new(_("Filter on:"));
 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 6);
 vbox = gtk_vbox_new(FALSE, FALSE);
 gtk_container_border_width(GTK_CONTAINER(frame), 6);
 gtk_container_add(GTK_CONTAINER(frame), vbox);
 gtk_widget_show(vbox);

 /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("Name"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_NAME", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_name);
 /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("Description"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_DESCRIPTION", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_description);
 /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("Summary"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_SUMMARY", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_summary);
 /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("Author"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_AUTHOR", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_author);
 /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("ID number"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_ID", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_id);
 /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("Category"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_CATEGORY", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_category);
 /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("CVE"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_CVE", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_cve);
  /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("BID"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_BID", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_bid);

  /*--------------------------------------------*/
 button = gtk_check_button_new_with_label(_("XREF"));
 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 3);
 gtk_widget_show(button);
 arg_add_value(ctrls, "FILTER_XREF", ARG_PTR, -1, button);
 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), filter_on_xref);

 gtk_widget_show(frame);

 gtk_widget_show(dialog);
 return ctrls;
}


int
ask_filter (struct plugin_filter * filter)
{
  struct arglist * ctrls = build_filter_dlog();
  GtkWidget * dialog;
  char * pattern = NULL;

  dialog = arg_get_value (ctrls, "WINDOW");

  switch (gtk_dialog_run(GTK_DIALOG(dialog)))
  {
    case GTK_RESPONSE_OK:
      pattern = (char*) gtk_entry_get_text(GTK_ENTRY(
        arg_get_value(ctrls,"ENTRY")));
      filter_on_name = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_NAME"))->active;
      filter_on_description = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_DESCRIPTION"))->active;
      filter_on_summary = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_SUMMARY"))->active;
      filter_on_author = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_AUTHOR"))->active;
      filter_on_id = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_ID"))->active;
      filter_on_category = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_CATEGORY"))->active;
      filter_on_bid = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_BID"))->active;
      filter_on_cve =  GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_CVE"))->active;
      filter_on_xref = GTK_TOGGLE_BUTTON(
        arg_get_value(ctrls, "FILTER_XREF"))->active;
      break;
    default: /* pattern remains NULL */
      break;
  }

  if (!pattern)
    filter->pattern = NULL;
  else
    filter->pattern = estrdup (pattern);

 filter->filter_on_name = filter_on_name;
 filter->filter_on_description = filter_on_description;
 filter->filter_on_summary = filter_on_summary;
 filter->filter_on_author = filter_on_author;
 filter->filter_on_id = filter_on_id;
 filter->filter_on_category = filter_on_category;
 filter->filter_on_cve = filter_on_cve;
 filter->filter_on_bid = filter_on_bid;
 filter->filter_on_xref = filter_on_xref;

 gtk_widget_destroy (dialog);
 arg_free (ctrls);
 return 0;
}
#endif /* defined(USE_GTK) */

#ifndef NS
#define NS 1024
#endif


#ifdef USE_GTK
/**
 * @brief Compares pattern against string.
 * 
 * @param str The string to compare against the pattern.
 * @param pat The pattern (regular expression).
 * 
 * @return -1 if pat is not an acceptable pattern.
 */
static int
match (char * str, char * pat)
{
  regex_t re;
  regmatch_t subs[NS];

  re_set_syntax(RE_SYNTAX_POSIX_EGREP);
  if(regcomp(&re, pat, REG_EXTENDED|REG_ICASE))
    {
      show_error(_("Invalid regular expression"));
      bzero(pat, strlen(pat));
      return -1;
    }
  if(regexec(&re, str, (size_t)NS, subs, 0) == 0)
    {
      regfree(&re);
      return 0;
    }
   regfree(&re);
   return 1;
}
#endif

int
filter_plugin (struct plugin_filter *filter, struct nessus_plugin * plugin)
{
  int ret    = 0; /* Don't filter it */
  int retval = 0;

#ifdef USE_GTK
  char * name        = plugin->name;
  char * description = nessus_plugin_get_description(plugin);
  char * summary     = plugin->summary;
  char * author      = plugin->copyright;
  char * oid         = plugin->oid;
  char * category    = plugin->category;
  char * cve         = plugin->cve;
  char * bid         = plugin->bid;
  char * xref        = plugin->xrefs;

  if (!filter->pattern || !strlen(filter->pattern))
    goto ret;

  if (filter->filter_on_name)
    {
      ret = match (name, filter->pattern);
      if(!ret) goto ret;
    }

  if (filter->filter_on_description)
    {
      ret = match (description, filter->pattern);
      if(!ret) goto ret;
    }

  if (filter->filter_on_summary)
    {
      ret = match (summary, filter->pattern);
      if (!ret) goto ret;
    }

  if (filter->filter_on_author)
    {
      ret = match (author, filter->pattern);
      if (!ret) goto ret;
    }

  if (filter->filter_on_category)
    {
      ret = match (category, filter->pattern);
      if (!ret) goto ret;
    }

  if (filter->filter_on_cve)
    {
      if (cve != NULL ) ret = match (cve, filter->pattern);
      else ret = 0;
      if (!ret)goto ret;
    }

  if (filter->filter_on_bid)
    {
      if (bid != NULL ) ret = match (bid, filter->pattern);
      else ret = 0;
      if (!ret) goto ret;
    }

  if (filter->filter_on_xref)
    {
      if (xref != NULL ) ret = match (xref, filter->pattern);
      else ret = 0;
      if (!ret) goto ret;
    }

 if (filter->filter_on_id)
   ret = match (oid, filter->pattern);

 retval = ret;

ret:
#endif

  return retval;
}
