/* $Id: report.c,v 1.8 2007-04-29 19:20:53 jan Exp $
 *
 * Copyright (C) 1998, 1999, 2000 Renaud Deraison
 * Copyright (C) 2004 by Intevation GmbH
 * Author(s):
 * Thomas Arendsen Hein <thomas@intevation.de>
 *
 * This program is free software under the GNU GPL (>=v2)
 * Read the file COPYING coming with the software for details.
 *
 * 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 "context.h"
#include "error_dlg.h"

#ifdef USE_GTK
#include <gtk/gtk.h>
#include "prefs_dialog/prefs_scope_tree.h"
#include "prefs_dialog/prefs_context.h"
#include "plugin_cache.h"
#include "nessus_plugin.h"
#endif

#include "report.h"
#include "backend.h"
#include "nbe_output.h"
#include "openvas_certificate_file.h"
#include "preferences.h"

/**
 * @brief Get the report filename (report_ctx_dir/report.nbe).
 * 
 * @param context The report- context.
 * 
 * @return Filename of report (must be g_freed) or NULL.
 */
gchar *
report_get_filename (struct context *context)
{
  gchar *report = NULL;

  if(context->type == CONTEXT_REPORT && context->dir)
    report = g_build_filename (context->dir, "report.nbe", NULL);

  return report;
}

/**
 * @brief Get the filename for a reports certificate cache
 * @brief (report_ctx_dir/certificates).
 * 
 * @param context The report- context.
 * 
 * @return Filename for reports certificate cache (must be g_freed) or NULL.
 */
gchar*
report_get_certificates_filename (struct context* context)
{
  gchar* report = NULL;

  if (context->type == CONTEXT_REPORT && context->dir)
    report = g_build_filename (context->dir, "certificates", NULL);

  return report;
}


/* reports back the highest number */
int
is_there_any_hole (struct arglist * arglist)
{
 int ret = 0;
 /* Pluto 25.6.00: with three level of return, real sort */
 while(arglist && arglist->next && (ret!=HOLE_PRESENT))
 {
  int tmp = 0;
  int tmp2 = 0;
  if(!arglist->name)
   {
    arglist = arglist->next;
    continue;
   }
  if(!strcmp(arglist->name, "REPORT"))tmp2 = HOLE_PRESENT;
  else if(!strcmp(arglist->name, "INFO"))tmp2 = WARNING_PRESENT;
  else if(!strcmp(arglist->name, "NOTE"))tmp2 = NOTE_PRESENT;
  else if(!strcmp(arglist->name, "FALSE"))tmp2 = FALSE_PRESENT;
  /*
   * Check in the sublist
   */
  if(arglist->type == ARG_ARGLIST)tmp = is_there_any_hole(arglist->value);
  if(tmp >= tmp2)tmp2 = tmp;
  if(tmp2 >= ret)ret = tmp2;
  arglist = arglist->next;
 }
 return(ret);
}

#ifdef USE_GTK

/**
 * @brief Copy plugin information.
 * 
 * @param context Context to which duplicates of the plugins will be added.
 * 
 * @param plugin Plugin-list.
 */
static void
copy_plugins (struct context *context, struct nessus_plugin *plugin)
{
  while (plugin)
  {
    context_add_plugin (context, nessus_plugin_duplicate(plugin));
    plugin = plugin->next;
  }
}


/**
 * @brief Saves report contents.
 * 
 * @param context The context to use (a child context will be created).
 * @param backend The backend index.
 * 
 * @param name A name for the report (a naming scheme is applied if NULL).
 */
void
report_save (struct context* context, int backend, const char* name)
{
  struct context *report_context;
  gchar *report_filename;
  int report_len = strlen("Report YYYYMMDD-HHMMSS") + 1;
  time_t t;
  int error;

  context = context_by_type(context, CONTEXT_SCOPE);
  if(!context)
  {
    show_error(_("report_save() called with illegal type"));
    return;
  }

  if(name)
    report_context = scopetree_new_with_parent(context, CONTEXT_REPORT,
	name, "");
  else
  {
    char* report_name = emalloc(report_len);
    t = time(NULL);
    strftime(report_name, report_len, "Report %Y%m%d-%H%M%S", localtime(&t));
    report_context = scopetree_new_with_parent(context, CONTEXT_REPORT,
	report_name, NULL);
    efree(&report_name);
  }

  if(!report_context)
  {
    show_error(_("report_save() couldn't create context"));
    return;
  }
  report_filename = report_get_filename (report_context);
  if(!report_filename)
  {
    show_error(_("report_save() couldn't find a report filename"));
    return;
  }

  error = backend_to_nbe(backend, report_filename);
  g_free (report_filename);
  if(error)
  {
    show_error(_("report_save() couldn't save the report"));
    return;
  }

  if (prefs_get_int(Global, "reports_use_plugin_cache"))
  {
    copy_plugins(report_context, context->plugins);
    copy_plugins(report_context, context->scanners);

    error = plugin_cache_write(report_context, "");
    if(error)
    {
      show_error(_("report_save() couldn't save the plugin information"));
      return;
    }

    /* by the time we get here, the report_context may already have got a
     * plugin tree because scopetree_new_with_parent may trigger GUI
     * updates, so we have to reset the tree. */
    context_reset_plugin_tree(report_context);
  }

  /* Save the certificate information (as of now) to 
     report_dir/certificate file */
  gchar* certfile = report_get_certificates_filename(report_context);
  if ( openvas_certificate_file_write(context, certfile) == FALSE)
    {
    show_error(_("report_save() couldn't save the certificate information"));
    if (certfile)
      g_free (certfile);
    return;
    }
  // Immidiately load, to make information available in report context
  report_context->signer_fp_certificates = openvas_certificate_file_read(certfile);
  g_free (certfile);

  prefs_context_update(report_context);
}


/**
 * @brief Opens the report.
 */
void
open_report (GtkWidget * dontcare, GtkWidget *nsr)
{
  const gchar *filename =
    gtk_file_selection_get_filename(GTK_FILE_SELECTION(nsr));
  int be = backend_import_report((char *)filename);

  if(be >= 0)
    {
      gchar *report_name = g_path_get_basename (filename);
      report_save (Context, be, report_name);
      g_free (report_name);
    }
}


/**
 * @brief Menu selection to open a report from file, pops up a file selector.
 */
void
open_report_selectfile ()
{
 GtkWidget * nsr;
 nsr = gtk_file_selection_new (_("Load file"));

 gtk_file_selection_set_filename (GTK_FILE_SELECTION(nsr), "");
 g_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (nsr)->ok_button),
                               "clicked", (GtkSignalFunc) open_report,(void *) nsr );

 g_signal_connect_swapped (GTK_OBJECT (GTK_FILE_SELECTION(nsr)->ok_button),
   					  "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
   					  (gpointer) nsr);

 g_signal_connect_swapped (GTK_OBJECT (GTK_FILE_SELECTION(nsr)->cancel_button),
   					  "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
   					  (gpointer) nsr);

 gtk_widget_show(nsr);
}
#endif
