/* OpenVAS-Client
 * $Id$
 * Description: Module for displaying infos of a specific ssh key pair.
 *
 * Authors:
 * Felix Wolfsteller <felix.wolfsteller@intevation.de>
 *
 * Copyright:
 * Copyright (C) 2008 Intevation GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * or, at your option, any later version 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * In addition, as a special exception, you have
 * permission to link the code of this program with the OpenSSL
 * library (or with modified versions of OpenSSL that use the same
 * license as OpenSSL), 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"

#ifdef USE_GTK
#include <gtk/gtk.h>
#include "context.h" /* for check_is_file */
#include "error_dlg.h"
#include "openvas_lsc_target_prep.h"
#include "openvas_lsc_user_deb.h" /* for openvas_lsc_user_deb_alien_found and _filename */
#include "openvas_lsc_user_makensis.h" /* for openvas_lsc_user_makensis_found and _filename */
#include "openvas_lsc_user_rpm.h" /* for openvas_lsc_user_rpm_generator_found and _filename  */
#include "openvas_ssh_login.h"
#include "preferences.h"
#include "ssh_key_info_form.h"

/** @file
 * @TODO The form handles more than just ssh keys by now. Should be refactored
 * (together with openvas_ssh_login etc, probably in favor of an
 * openvas_lsc_credentials module)
 */

/**
 * @brief Fills a ssh_key_info_form with values of a openvas_ssh_login struct
 * and sets  text fields (gtk_entries) to be non-editable.
 * 
 * If NULL is passed as second argument, the form will be cleared (all fields
 * set to the empty string).
 * 
 * @param form The initialized ssh_key_info_form.
 * @param loginfo The openvas_ssh_login struct to take values from or NULL to
 *                clear form.
 */
void
ssh_key_info_form_fill(ssh_key_info_form* form, openvas_ssh_login* loginfo)
{
  gchar* credentials_path;

  if(loginfo == NULL)
  {
    gtk_entry_set_text(GTK_ENTRY(form->name), "");
    gtk_entry_set_text(GTK_ENTRY(form->username), "");
    gtk_entry_set_text(GTK_ENTRY(form->userpassword), "");
    gtk_entry_set_text(GTK_ENTRY(form->public_key_path), "");
    gtk_entry_set_text(GTK_ENTRY(form->private_key_path), "");
    gtk_entry_set_text(GTK_ENTRY(form->comment), "");
    gtk_entry_set_text(GTK_ENTRY(form->ssh_key_passphrase), "");
    gtk_entry_set_text(GTK_ENTRY(form->rpm_location), "");
    gtk_entry_set_text(GTK_ENTRY(form->deb_location), "");
    gtk_entry_set_text(GTK_ENTRY(form->exe_location), "");
  }
  else
  {
    gtk_entry_set_text(GTK_ENTRY(form->name), loginfo->name);
    gtk_entry_set_text(GTK_ENTRY(form->username), loginfo->username);
    gtk_entry_set_text(GTK_ENTRY(form->userpassword), loginfo->userpassword);
    gtk_entry_set_text(GTK_ENTRY(form->public_key_path), loginfo->public_key_path);
    gtk_entry_set_text(GTK_ENTRY(form->private_key_path), loginfo->private_key_path);
    gtk_entry_set_text(GTK_ENTRY(form->comment), loginfo->comment);
    gtk_entry_set_text(GTK_ENTRY(form->ssh_key_passphrase), loginfo->ssh_key_passphrase);

    // Exchange file extensions
    credentials_path = openvas_lsc_user_rpm_filename (loginfo->name);

    if (check_is_file (credentials_path) == 0)
        gtk_entry_set_text (GTK_ENTRY(form->rpm_location), "-- rpm not found --");
    else
        gtk_entry_set_text(GTK_ENTRY(form->rpm_location), credentials_path);

    g_free (credentials_path);
    credentials_path = openvas_lsc_user_deb_filename (loginfo->name);

    if (check_is_file (credentials_path) == 0)
        gtk_entry_set_text (GTK_ENTRY(form->deb_location), "-- deb not found --");
    else
        gtk_entry_set_text(GTK_ENTRY(form->deb_location), credentials_path);

    g_free (credentials_path);
    credentials_path = openvas_lsc_user_makensis_filename (loginfo->name);

    if (check_is_file (credentials_path) == 0)
        gtk_entry_set_text (GTK_ENTRY(form->exe_location), "-- exe not found --");
    else
        gtk_entry_set_text(GTK_ENTRY(form->exe_location), credentials_path);

    g_free (credentials_path);
  }

  gtk_entry_set_editable(GTK_ENTRY(form->name), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->username), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->userpassword), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->public_key_path), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->private_key_path), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->comment), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->ssh_key_passphrase), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->rpm_location), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->deb_location), FALSE);
  gtk_entry_set_editable(GTK_ENTRY(form->exe_location), FALSE);
}


/**
 * @brief Fills filenames into the two filename entries in a ssh_key_info_form.
 * 
 * The filenames are generated from the name of the ssh_login account.
 * This function is a callback function for the entry holding this name and
 * called at each key stroke.
 * 
 * @param entry Gtk Entry (callback).
 * @param form ssh_login for of which the filename entries shall be filled.
 */
static void
name_typed_in_cb(GtkEntry *entry, ssh_key_info_form* form)
{
  const char* name    = gtk_entry_get_text(entry);

  char* home          = prefs_get_nessushome();

  gchar* canoname     = g_strdup (name);

  g_strcanon (canoname, LEGAL_FILENAME_CHARS, '_');

  gchar* pubkey_path  = g_strdup_printf("%s/.openvas/.ssh/%s.pub", home, canoname);
  gchar* privkey_path = g_strdup_printf("%s/.openvas/.ssh/%s.p8",  home, canoname);

  gtk_entry_set_text(GTK_ENTRY(form->public_key_path),  pubkey_path);
  gtk_entry_set_text(GTK_ENTRY(form->private_key_path), privkey_path);

  if (openvas_lsc_user_rpm_generator_found() == TRUE)
    {
      gchar* rpm_path = openvas_lsc_user_rpm_filename (canoname);
      gtk_entry_set_text (GTK_ENTRY(form->rpm_location), rpm_path);
      g_free (rpm_path);
      // Can build deb from rpm only if can build rpm
      if (openvas_lsc_user_deb_alien_found() == TRUE)
        {
          gchar* deb_path = openvas_lsc_user_deb_filename (canoname);
          gtk_entry_set_text (GTK_ENTRY(form->deb_location),
                              g_strcanon (deb_path, LEGAL_FILENAME_CHARS, '_'));
          g_free (deb_path);
        }
    }

  if (openvas_lsc_user_makensis_found() == TRUE)
    {
      gchar* exe_path     = openvas_lsc_user_makensis_filename (canoname);
      gtk_entry_set_text (GTK_ENTRY(form->exe_location),
                          g_strcanon (exe_path, LEGAL_FILENAME_CHARS, '_'));
      g_free (exe_path);
    }

  g_free (pubkey_path);
  g_free (privkey_path);
}

/**
 * @brief Adds tooltips to all text entries.
 * @param form The form to set tooltips to.
 */
static void
add_tooltips (ssh_key_info_form* form)
{
  GtkTooltips* form_tips;
  form_tips = gtk_tooltips_new ();
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->name,
                          _("Name for this account."),
                          _("Name for this account."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->username,
                          _("The local username of this account."),
                          _("The local username of this account."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->username,
                          _("The local username of this account."),
                          _("The local username of this account."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->userpassword,
                          _("The password of the user of this account."),
                          _("The password of the user of this account."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->public_key_path,
                          _("Path to the public key file (automatically set by OpenVAS)."),
                          _("Path to the public key file (automatically set by OpenVAS)."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->private_key_path,
                          _("Path to the private key file (automatically set by OpenVAS)."),
                          _("Path to the private key file (automatically set by OpenVAS)."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->ssh_key_passphrase,
                          _("Passphrase for the private key."),
                          _("Passphrase for the private key."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->comment,
                          _("Comment to be used when keys are created."),
                          _("Comment to be used when keys are created."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->deb_location,
                          _("Path to a debian package that installs this credentials (automatically set by OpenVAS if you have alien installed)."),
                          _("Path to a debian package that installs this credentials (automatically set by OpenVAS if you have alien installed)."));
  gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->rpm_location,
                          _("Path to a rpm package that 'installs' these credentials (automatically set by OpenVAS if you have the rpm generator installed)."),
                          _("Path to a rpm package that 'installs' these credentials (automatically set by OpenVAS if you have the rpm generator installed)."));
    gtk_tooltips_set_tip (GTK_TOOLTIPS (form_tips), form->exe_location,
                          _("Path to a .exe installer that 'installs' these credentials (automatically set by OpenVAS if you have makensis installed)."),
                          _("Path to a .exe installer that 'installs' these credentials (automatically set by OpenVAS if you have makensis installed)."));
}

/**
 * @brief Initializes a ssh_key_info_form.
 * 
 * A ssh_key_info_form is a gtk_box with labels, text entries and
 * buttons, reflecting data of a openvas_ssh_login.
 * This is the only way to initialize a ssh_key_info_form.
 * Values of an openvas_ssh_login can be inserted quickly, calling
 * ssh_key_info_form_fill.
 * Similarly, the an openvas_ssh_login can be created using this values by 
 * calling ssh_key_info_form_produce_login.
 * Before trying to create keypairs for this openvas_ssh_login, the input should
 * be validated (ssh_key_info_form_validated).
 * 
 * @return Fresh ssh_key_info_form.
 */
ssh_key_info_form*
ssh_key_info_form_create()
{
  GtkWidget* label;
  GtkWidget* table;
  
  ssh_key_info_form* form = emalloc (sizeof(ssh_key_info_form));
  
  /* Init dynamical content */
  form->box = gtk_vbox_new(TRUE, 5);
  
  form->name = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(form->name), "");
  
  form->username = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(form->username), "");
  
  form->userpassword = gtk_entry_new();
  gtk_entry_set_visibility(GTK_ENTRY(form->userpassword), FALSE);
  gtk_entry_set_text(GTK_ENTRY(form->userpassword), "");
  
  form->public_key_path = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(form->public_key_path), "");
  
  form->private_key_path = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(form->private_key_path), "");
  
  form->ssh_key_passphrase= gtk_entry_new();
  gtk_entry_set_visibility(GTK_ENTRY(form->ssh_key_passphrase), FALSE);
  gtk_entry_set_text(GTK_ENTRY(form->ssh_key_passphrase), "");
  
  form->comment = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(form->comment), "");

  form->rpm_location = gtk_entry_new ();
  if (openvas_lsc_user_rpm_generator_found () == TRUE)
    gtk_entry_set_text(GTK_ENTRY (form->rpm_location), "");
  else
    gtk_entry_set_text(GTK_ENTRY (form->rpm_location), "rpm generator script not found");

  form->deb_location = gtk_entry_new ();
  if (openvas_lsc_user_deb_alien_found() == TRUE && openvas_lsc_user_rpm_generator_found () == TRUE)
    gtk_entry_set_text (GTK_ENTRY (form->deb_location), "");
  else
    gtk_entry_set_text (GTK_ENTRY (form->deb_location), _("alien or rpm not found in path"));

  form->exe_location = gtk_entry_new ();
  if (openvas_lsc_user_makensis_found() == TRUE)
    gtk_entry_set_text(GTK_ENTRY (form->exe_location), "");
  else
    gtk_entry_set_text(GTK_ENTRY (form->exe_location), _("makensis not found in path"));

  /* Setup layouting table */
  int row = 1;
  int col = 1;
  table = gtk_table_new(10, 2, FALSE);
  gtk_box_pack_start(GTK_BOX(form->box), table, FALSE, FALSE, 5);
  
  /* Start packing */
  label = gtk_label_new(_("Account name:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->name, col, col+1, row, row+1);
  g_signal_connect(GTK_OBJECT(form->name), "changed", (GtkSignalFunc) name_typed_in_cb, form);
  
  row++;
  col = 1;
  label = gtk_label_new(_("SSH login name:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->username, col, col+1, row, row+1);
  
  row++;
  col = 1;
  label = gtk_label_new(_("(optional) SSH login password:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->userpassword, col, col+1, row, row+1);
  
  row++;
  col = 1;
  label = gtk_label_new(_("SSH public key:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->public_key_path, col, col+1, row, row+1);
  col++;
    
  row++;
  col = 1;
  label = gtk_label_new(_("SSH private key:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->private_key_path, col, col+1, row, row+1);
  col++;
  
  row++;
  col = 1;
  label = gtk_label_new(_("SSH key passphrase:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->ssh_key_passphrase, col, col+1, row, row+1);
  
  row++;
  col = 1;
  label = gtk_label_new(_("Comment:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->comment, col, col+1, row, row+1);
  
  row++;
  col = 1;
  label = gtk_label_new(_("RPM package:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->rpm_location, col, col+1, row, row+1);
  
  row++;
  col = 1;
  label = gtk_label_new(_("deb package:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->deb_location, col, col+1, row, row+1);
  
  row++;
  col = 1;
  label = gtk_label_new(_("Windows installer:"));
  gtk_table_attach_defaults(GTK_TABLE(table), label, col, col+1, row, row+1);
  col++;
  gtk_table_attach_defaults(GTK_TABLE(table), form->exe_location, col, col+1, row, row+1);

  add_tooltips (form);

  return form;
}


/**
 * @brief Validates the input of entries in a ssh_key_info_form.
 * 
 * @param form Form to be checked.
 * 
 * @return FALSE if something should be corrected (shows info message what),
 *         TRUE if values seem ok.
 */
gboolean
ssh_key_info_form_validated(ssh_key_info_form* form)
{
  // Following strings belong to the gtk widgets, do not touch them
  const char* passphrase = gtk_entry_get_text(GTK_ENTRY(form->ssh_key_passphrase));
  const char* comment = gtk_entry_get_text(GTK_ENTRY(form->comment));
  const char* uname = gtk_entry_get_text(GTK_ENTRY(form->username));
  const char* name = gtk_entry_get_text(GTK_ENTRY(form->name));
  
  // Validate from top to bottom (in gui)
  if(strlen(name) < 4){ /* RATS: ignore. String termination is ensured by gtk_entry_get_text. */
    show_info(_("Please provide a better name."));
    return FALSE;
  }
  
  if(strlen(uname) < 4) /* RATS: ignore. String termination is ensured by gtk_entry_get_text. */
  {
    show_info(_("Please provide a longer username."));
    return FALSE;
  }
  
  if(strlen(passphrase) < 5){ /* RATS: ignore. String termination is ensured by gtk_entry_get_text. */
    show_info(_("Please provide a passphrase with more then 5 characters."));
    return FALSE;
  }
  
  if(strlen(comment) < 4) /* RATS: ignore. String termination is ensured by gtk_entry_get_text. */
  {
    show_info(_("Please provide a better comment for public key."));
    return FALSE;
  }
  
  if(strstr(comment," ") != NULL)
  {
    show_info(_("Comment must not contain spaces."));
    return FALSE;
  }
  
  return TRUE;
}


/**
 * @brief Initializes a openvas_ssh_login with the values of a ssh_key_info_form.
 * 
 * @param form The ssh_key_info_form to take values from.
 * 
 * @return A fresh openvas_ssh_login, filled with the values of a ssh_key_info_form.
 */
openvas_ssh_login*
ssh_key_info_form_produce_login(ssh_key_info_form* form)
{
  // Following strings belong to the gtk widgets, do not touch them
  const char* pubkey_file = gtk_entry_get_text(GTK_ENTRY(form->public_key_path));
  const char* privkey_file = gtk_entry_get_text(GTK_ENTRY(form->private_key_path));
  const char* passphrase = gtk_entry_get_text(GTK_ENTRY(form->ssh_key_passphrase));
  const char* comment = gtk_entry_get_text(GTK_ENTRY(form->comment));
  const char* uname = gtk_entry_get_text(GTK_ENTRY(form->username));
  const char* name = gtk_entry_get_text(GTK_ENTRY(form->name));
  const char* upass = gtk_entry_get_text(GTK_ENTRY(form->userpassword));

  openvas_ssh_login* loginfo = openvas_ssh_login_new(estrdup(name), estrdup(pubkey_file),
      estrdup(privkey_file), estrdup(passphrase),
      estrdup(comment), estrdup(uname), estrdup(upass));
  return loginfo;
}

/**
 * @brief Destroys associated widgets.
 * 
 * @param form The form to free.
 */
void ssh_key_info_form_free(ssh_key_info_form* form)
{
  if(form == NULL)
    return;
  if(form->box)
    gtk_widget_destroy(form->box);
  if(form->name)
    gtk_widget_destroy(form->name);
  if(form->username)
    gtk_widget_destroy(form->username);
  if(form->userpassword)
    gtk_widget_destroy(form->userpassword);
  if(form->public_key_path)
    gtk_widget_destroy(form->public_key_path);
  if(form->private_key_path)
    gtk_widget_destroy(form->private_key_path);
  if(form->ssh_key_passphrase)
    gtk_widget_destroy(form->ssh_key_passphrase);
  if(form->comment)
    gtk_widget_destroy(form->comment);
  if (form->rpm_location)
    gtk_widget_destroy(form->rpm_location);
  if (form->deb_location)
    gtk_widget_destroy(form->deb_location);
  if (form->exe_location)
    gtk_widget_destroy(form->exe_location);
  efree(&form);
}

#endif /* USE_GTK */
