/* main.c - the main file :-) */

/* by will darling */
/* february, 1998  */

/*
 *  This work is released under the GPL - Gnu General Public License,
 *  Version 2. You may copy and re-distribute this code. The code is
 *  copyright (c) Will Darling, 1998.
 *
 */

/*
 *  Phut Klan encryption. Based on blowfish encryption.
 *  Program first created in february, 1998.
 *  gtk interface first implemented on february 6th.
 *
 */

/*
 * version info:
 * 0.001 - february 1st - command line - simple encryption
 * 0.002 - february 6th - gtk interface
 * 0.003 - february 27th - done gtk. file selection box - bugs
 * 0.004 - march 19th - fsb done - new: edit box, passwd box - bugs
 * 0.005 - march 20th - passwd box works. edit box coming along. bug fixes
 *                    - added a progress bar that almost works - a few bugs
 * 0.006 - march 21st - progress bar, menu, LOTS - netscape remote launch
 *                    - now I'm just gonna put these in README.
 */

/* includes */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include "main.h"
#include "encrypt.h"

/* includes for front end */
#include <gtk/gtk.h>

/* includes for pixmaps */
#include "pix/exit.xpm"
#include "pix/edit.xpm"
#include "pix/egg.xpm"
#include "pix/lock.xpm"
#include "pix/pref.xpm"
#include "pix/sign.xpm"
#include "pix/unlock.xpm"
#include "pix/recycle.xpm"
#include "pix/closedf.xpm"
#include "pix/openf.xpm"
#include "pix/icon.xbm"

GtkWidget *filename_entry, *filew, *entry, *sub_window;
GtkWidget *pixbox5, *file_button;
int fetype = GUI;

/* main encryption and decryption external functions */
extern int enc(char *filename, char *word, int fe);
extern int dec(char *filename, char *word, int fe);

void setup_enc(void);
void setup_dec(void);
void cancel_passwd(void);
void fileerror(char *filename);
void phut(void);
void switch_pix(GtkWidget *parent);
void change_style(void);
void easteregg(void);
int file_close(void);
void update_progress(void);
void file_ok_sel(GtkWidget *widget, gpointer *data);
void file_can_sel(GtkWidget *widget, gpointer *data);
void delete_event(GtkWidget *widget, GdkEvent *event, gpointer *data);

void goenc(void);
void godec(void);

extern void about(void);
extern void help(void);
extern void pref(void);
extern void edit(void);
extern void sign(void);

/* create a new hbox with an image and a label packed in & return the box */

GtkWidget *xpm_label_box(GtkWidget *parent, gchar **xpm_filename, gchar *label_text) 
{
  GtkWidget *pixbox;
  GtkWidget *label;
  GtkWidget *pixmapwid;
  GdkPixmap *pixmap;
  GdkColor c;
  GdkBitmap *bitmap;
  
  gtk_widget_realize(parent);

  pixbox = gtk_hbox_new(FALSE, 0);
  gtk_container_border_width(GTK_CONTAINER(pixbox), 2);

  pixmap = gdk_pixmap_create_from_xpm_d(parent->window, &bitmap,
				        &c, xpm_filename);
  pixmapwid = gtk_pixmap_new(pixmap, bitmap);

  label = gtk_label_new(label_text);
  gtk_box_pack_start(GTK_BOX(pixbox), pixmapwid, FALSE, FALSE, 3);
  gtk_box_pack_start(GTK_BOX(pixbox), label, FALSE, FALSE, 3);
  
  gtk_widget_show(pixmapwid);
  gtk_widget_show(label);

  return(pixbox);
}

void delete_event(GtkWidget *widget, GdkEvent *event, gpointer *data)
{
  int error;

  if((error = file_close()) != 0)
    fprintf(stderr, "uhh-oh!\n");
  phut();

  gtk_main_quit();
}

int main(int argc, char **argv)
{ 
  static GtkWidget *window;
  GtkWidget *enc_button, *dec_button, *exit_button, *edit_button;
  GtkWidget *mainbox, *box1;
  GtkWidget *filelabel;
  GtkWidget *pixbox, *pixbox2, *pixbox3, *pixbox4;
  GtkTooltips *tooltips;
  GtkWidget *pixboxA, *pixboxB, *pixboxC, *pixboxD, *pixboxE, *pixboxF, *pixboxG;
  GdkBitmap *icon;

  /* menu stuff */
  GtkWidget *menubar;
  GtkWidget *menu, *menu2, *menu3, *file_menu, *edit_menu, *help_menu;
  GtkWidget *encrypt_item, *decrypt_item, *sign_item, *about_item, *help_item, *exit_item, *pref_item;

  int c;
  const char *prompt = "password:";
  char *password;

  gtk_init(&argc, &argv);

  while((c=getopt(argc, argv, "d:e:hvs")) != EOF)
  {
    switch(c)
    {
	case 'd':
	  password = getpass(prompt);
	  fetype = CMD_LINE;
	  dec(argv[2], password, CMD_LINE);
	  exit(0);
	  break;
	case 'e':
	  password = getpass(prompt);
	  fetype = CMD_LINE;
	  enc(argv[2], password, CMD_LINE);
	  exit(0);
	  break;
	case 'h':
	  fprintf(stderr, "type encrypt and voila!\n");
	  exit(0);
	  break;
	case 'v':
	  fprintf(stderr, "v%s\n", version);
	  exit(0);
	  break;
	case 's':
	  fprintf(stderr, "not done yet\n");
	  exit(0);
	  break;
	default:
	  exit(1);
	  break;
    }
  }

  /* change the look of the gui */
  /* change_style(); */

  /* setup the gui */
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "phut klan encryption");

  gtk_signal_connect(GTK_OBJECT(window), "delete_event",
		     GTK_SIGNAL_FUNC(delete_event), NULL);

  gtk_widget_realize(window);
  icon = gdk_bitmap_create_from_data(window->window, icon_bits, icon_width, icon_height);
  gdk_window_set_icon(window->window, NULL, icon, icon);
  gdk_window_set_icon_name(window->window, "pkencrypt");

  /* gui objects */
  mainbox = gtk_vbox_new(FALSE, 0);
  box1 = gtk_hbox_new(FALSE, 0);
  gtk_container_border_width(GTK_CONTAINER(box1), 10);
  gtk_container_add(GTK_CONTAINER(window), mainbox);
  enc_button = gtk_button_new();
  dec_button = gtk_button_new();
  exit_button = gtk_button_new();
  file_button = gtk_button_new();
  edit_button = gtk_button_new();
  filelabel = gtk_label_new("Filename: ");
  filename_entry = gtk_entry_new();
  filew = gtk_file_selection_new("File selection");
  tooltips = gtk_tooltips_new();

  /**************** menu setup ****************/

  menubar = gtk_menu_bar_new();
  menu = gtk_menu_new();
  menu2 = gtk_menu_new();
  menu3 = gtk_menu_new();

  encrypt_item = gtk_menu_item_new();
  decrypt_item = gtk_menu_item_new();
  sign_item = gtk_menu_item_new();
  pref_item = gtk_menu_item_new();
  about_item = gtk_menu_item_new();
  help_item = gtk_menu_item_new();
  exit_item = gtk_menu_item_new();

  file_menu = gtk_menu_item_new_with_label("File");
  edit_menu = gtk_menu_item_new_with_label("Edit");
  help_menu = gtk_menu_item_new_with_label("Help");

  gtk_menu_append(GTK_MENU(menu), encrypt_item);
  gtk_menu_append(GTK_MENU(menu), decrypt_item);
  gtk_menu_append(GTK_MENU(menu), sign_item);
  gtk_menu_append(GTK_MENU(menu), exit_item);
  gtk_menu_append(GTK_MENU(menu2), pref_item);
  gtk_menu_append(GTK_MENU(menu3), about_item);
  gtk_menu_append(GTK_MENU(menu3), help_item);

  gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_menu), menu);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_menu), menu2);
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_menu), menu3);
  gtk_menu_bar_append(GTK_MENU_BAR(menubar), file_menu);
  gtk_menu_bar_append(GTK_MENU_BAR(menubar), edit_menu);
  gtk_menu_bar_append(GTK_MENU_BAR(menubar), help_menu);

  pixboxA = xpm_label_box(window, lock_xpm, "Encrypt");
  gtk_widget_show(pixboxA);
  gtk_container_add(GTK_CONTAINER(encrypt_item), pixboxA);

  pixboxB = xpm_label_box(window, unlock_xpm, "Decrypt");
  gtk_widget_show(pixboxB);
  gtk_container_add(GTK_CONTAINER(decrypt_item), pixboxB);

  pixboxC = xpm_label_box(window, sign_xpm, "Digitally Sign");
  gtk_widget_show(pixboxC);
  gtk_container_add(GTK_CONTAINER(sign_item), pixboxC);

  pixboxD = xpm_label_box(window, pref_xpm, "Preferences");
  gtk_widget_show(pixboxD);
  gtk_container_add(GTK_CONTAINER(pref_item), pixboxD);

  pixboxE = xpm_label_box(window, exit_xpm, "Exit");
  gtk_widget_show(pixboxE);
  gtk_container_add(GTK_CONTAINER(exit_item), pixboxE);

  pixboxF = xpm_label_box(window, recycle_xpm, "About");
  gtk_widget_show(pixboxF);
  gtk_container_add(GTK_CONTAINER(about_item), pixboxF);

  pixboxG = xpm_label_box(window, recycle_xpm, "Help");
  gtk_widget_show(pixboxG);
  gtk_container_add(GTK_CONTAINER(help_item), pixboxG);

  /* connect 'em */
  gtk_signal_connect(GTK_OBJECT(encrypt_item), "activate",
		     GTK_SIGNAL_FUNC(setup_enc), (gpointer) "Encrypt");
  gtk_signal_connect(GTK_OBJECT(decrypt_item), "activate",
		     GTK_SIGNAL_FUNC(setup_dec), (gpointer) "Decrypt");
  gtk_signal_connect(GTK_OBJECT(sign_item), "activate",
		     GTK_SIGNAL_FUNC(sign), NULL);
  gtk_signal_connect(GTK_OBJECT(exit_item), "activate",
		     GTK_SIGNAL_FUNC(delete_event), NULL);
  gtk_signal_connect(GTK_OBJECT(pref_item), "activate",
		     GTK_SIGNAL_FUNC(pref), NULL);
  gtk_signal_connect(GTK_OBJECT(about_item), "activate",
		     GTK_SIGNAL_FUNC(about), NULL);
  gtk_signal_connect(GTK_OBJECT(help_item), "activate",
		     GTK_SIGNAL_FUNC(help), NULL);

  /* show 'em */
  gtk_widget_show(encrypt_item);
  gtk_widget_show(decrypt_item);
  gtk_widget_show(sign_item);
  gtk_widget_show(exit_item);
  gtk_widget_show(pref_item);
  gtk_widget_show(about_item);
  gtk_widget_show(help_item);
  gtk_widget_show(file_menu);
  gtk_widget_show(edit_menu);
  gtk_widget_show(help_menu);
  gtk_widget_show(menubar);

  /************ done *****************/

  gtk_signal_connect(GTK_OBJECT(enc_button), "clicked",
		     GTK_SIGNAL_FUNC(setup_enc), (gpointer) "Encrypt");
  gtk_signal_connect(GTK_OBJECT(dec_button), "clicked",
		     GTK_SIGNAL_FUNC(setup_dec), (gpointer) "Decrypt");
  gtk_signal_connect(GTK_OBJECT(exit_button), "clicked",
		     GTK_SIGNAL_FUNC(delete_event), (gpointer) "Exit");
  gtk_signal_connect(GTK_OBJECT(file_button), "clicked",
		     GTK_SIGNAL_FUNC(switch_pix), (gpointer)window);
  gtk_signal_connect(GTK_OBJECT(edit_button), "clicked",
		     GTK_SIGNAL_FUNC(edit), (gpointer) "Edit");
  gtk_signal_connect(GTK_OBJECT(filew), "delete_event",
		     (GtkSignalFunc) file_can_sel, filew);
  gtk_signal_connect(GTK_OBJECT(enc_button), "clicked",
		     GTK_SIGNAL_FUNC(easteregg), NULL);

  /* setup the ok and cancel buttons in the file window */
  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->ok_button),
		     "clicked", (GtkSignalFunc) file_ok_sel, filew);
  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->cancel_button),
		     "clicked", (GtkSignalFunc) file_can_sel, filew);


  /* setup the encrypt button with a pixmap */
  pixbox = xpm_label_box(window, lock_xpm, "Encrypt");
  gtk_widget_show(pixbox);
  gtk_container_add(GTK_CONTAINER(enc_button), pixbox);

  /* setup the decrypt button with a pixmap */
  pixbox2 = xpm_label_box(window, unlock_xpm, "Decrypt");
  gtk_widget_show(pixbox2);
  gtk_container_add(GTK_CONTAINER(dec_button), pixbox2);

  /* setup the edit button with a pixmap */
  pixbox3 = xpm_label_box(window, edit_xpm, "Edit");
  gtk_widget_show(pixbox3);
  gtk_container_add(GTK_CONTAINER(edit_button), pixbox3);

  /* setup the exit button with a pixmap */
  pixbox4 = xpm_label_box(window, exit_xpm, "Exit");
  gtk_widget_show(pixbox4);
  gtk_container_add(GTK_CONTAINER(exit_button), pixbox4);

  /* setup the file window button with an xpm */
  pixbox5 = xpm_label_box(window, closedf_xpm, "");
  gtk_widget_show(pixbox5);
  gtk_container_add(GTK_CONTAINER(file_button), pixbox5);

  /* initialize tooltips on stuff */
  gtk_tooltips_set_tip(tooltips, enc_button, "Click here to encrypt", "ContextHelp/buttons/1");
  gtk_tooltips_set_tip(tooltips, dec_button, "Click here to decrypt", "ContextHelp/buttons/2");
  gtk_tooltips_set_tip(tooltips, exit_button, "Click here to exit", "ContextHelp/buttons/3");
  gtk_tooltips_set_tip(tooltips, file_button, "Click here to choose a file", "ContextHelp/buttons/4");
  gtk_tooltips_set_tip(tooltips, edit_button, "Click here to edit the file", "ContextHelp/buttons/5");
  gtk_tooltips_set_tip(tooltips, filename_entry, "Enter filename to encrypt/decrypt", "ContextHelp/buttons/6");

  gtk_box_pack_start(GTK_BOX(mainbox), menubar, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(mainbox), box1, TRUE, TRUE, 0);

  gtk_box_pack_start(GTK_BOX(box1), filelabel, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box1), filename_entry, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box1), file_button, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box1), edit_button, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box1), enc_button, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box1), dec_button, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box1), exit_button, TRUE, TRUE, 0);

  gtk_widget_show(enc_button);
  gtk_widget_show(dec_button);
  gtk_widget_show(file_button);
  gtk_widget_show(edit_button);
  gtk_widget_show(filelabel);
  gtk_widget_show(filename_entry);
  gtk_widget_show(exit_button);
  gtk_widget_show(box1);
  gtk_widget_show(mainbox);
  gtk_widget_show(window);

  gtk_main();

  return 0;
}

void setup_enc(void)
{
  GtkWidget *ok_button, *cancel_button;
  GtkWidget *label;

  sub_window = gtk_dialog_new();
  ok_button = gtk_button_new_with_label("Ok");
  cancel_button = gtk_button_new_with_label("Cancel");
  entry = gtk_entry_new();
  label = gtk_label_new("Password:");

  gtk_entry_set_visibility((GtkEntry *)entry, FALSE);

  gtk_signal_connect_object(GTK_OBJECT(ok_button), "clicked",
		     GTK_SIGNAL_FUNC(goenc), NULL);
  gtk_signal_connect(GTK_OBJECT(cancel_button), "clicked",
		     GTK_SIGNAL_FUNC(cancel_passwd), NULL);

  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->vbox), label, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->vbox), entry, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->action_area), ok_button, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->action_area), cancel_button, TRUE, TRUE, 0);

  gtk_widget_show(label);
  gtk_widget_show(entry);
  gtk_widget_show(ok_button);
  gtk_widget_show(cancel_button);
  gtk_widget_show(sub_window);
}

void setup_dec(void)
{
  GtkWidget *ok_button, *cancel_button;
  GtkWidget *label;

  sub_window = gtk_dialog_new();
  ok_button = gtk_button_new_with_label("Ok");
  cancel_button = gtk_button_new_with_label("Cancel");
  entry = gtk_entry_new();
  label = gtk_label_new("Password:");

  gtk_entry_set_visibility((GtkEntry *)entry, FALSE);

  gtk_signal_connect_object(GTK_OBJECT(ok_button), "clicked",
		     GTK_SIGNAL_FUNC(godec), NULL);
  gtk_signal_connect(GTK_OBJECT(cancel_button), "clicked",
		     GTK_SIGNAL_FUNC(cancel_passwd), NULL);

  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->vbox), label, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->vbox), entry, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->action_area), ok_button, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->action_area), cancel_button, TRUE, TRUE, 0);

  gtk_widget_show(label);
  gtk_widget_show(entry);
  gtk_widget_show(ok_button);
  gtk_widget_show(cancel_button);
  gtk_widget_show(sub_window);

}

void file_ok_sel(GtkWidget *widget, gpointer *data)
{
  gtk_entry_set_text(GTK_ENTRY(filename_entry),
                     gtk_file_selection_get_filename(GTK_FILE_SELECTION(filew)));

  gtk_widget_destroy(pixbox5);
  pixbox5 = xpm_label_box(filew, closedf_xpm, "");
  gtk_widget_show(pixbox5);
  gtk_container_add(GTK_CONTAINER(file_button), pixbox5);

  gtk_widget_hide(filew);
}

void file_can_sel(GtkWidget *widget, gpointer *data)
{
  gtk_widget_destroy(pixbox5);
  pixbox5 = xpm_label_box(filew, closedf_xpm, "");
  gtk_widget_show(pixbox5);
  gtk_container_add(GTK_CONTAINER(file_button), pixbox5);

  gtk_widget_hide(filew);
}

int file_close(void)
{
  extern FILE *input;
  extern FILE *output;

  if(input != NULL)
  	fclose(input);
  if(output != NULL)
  	fclose(output);

  return 0;
}

void switch_pix(GtkWidget *parent)
{
  gtk_widget_destroy(pixbox5);
  pixbox5 = xpm_label_box(parent, openf_xpm, "");
  gtk_widget_show(pixbox5);
  gtk_container_add(GTK_CONTAINER(file_button), pixbox5);

  gtk_widget_show(filew);
}

void fileerror(char *filename)
{
  GtkWidget *label;
  GtkWidget *button;
  char message[100];

  /* if(sub_window) gtk_widget_destroy(sub_window); */

  sub_window = gtk_dialog_new();

  sprintf(message, "%s: no such file or permission denied", filename);

  button = gtk_button_new_with_label("Ok");
  label = gtk_label_new(message);

  gtk_signal_connect(GTK_OBJECT(button), "clicked",
		     GTK_SIGNAL_FUNC(cancel_passwd), (gpointer) "Ok");
 
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->vbox), label, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sub_window)->action_area), button, TRUE, TRUE, 0);

  gtk_widget_show(label);
  gtk_widget_show(button);
  gtk_widget_show(sub_window);
}

void cancel_passwd(void)
{
  gtk_widget_destroy(sub_window);
}

void easteregg(void)
{
  GtkWidget *egg_window;
  GtkWidget *pixmapwid;
  GdkPixmap *pixmap;
  GdkBitmap *mask;
  GdkColor  c;
  char *buf;
  extern char secret[];
  int w;

  buf=gtk_entry_get_text(GTK_ENTRY(filename_entry));

  for(w=0; w<strlen(secret); w++)
  {
    if(w!=4)
      secret[w]++;
  }

  if(strcmp(buf, secret) == 0)
  {
    egg_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(egg_window), "it's easter all over again!");

    /* load an easter egg pixmap */
    gtk_widget_realize(egg_window);
    pixmap = gdk_pixmap_create_from_xpm_d(egg_window->window, &mask,
				          &c, egg_xpm);
    pixmapwid = gtk_pixmap_new(pixmap, mask);

    gtk_container_add(GTK_CONTAINER(egg_window), pixmapwid);

    gtk_widget_show(pixmapwid);
    gtk_widget_show(egg_window);
  }
}

void phut(void)
{
  char *phut = {"pk enc\n\0"};
  printf(phut);

  if(sound_opt==1)
    system("cat e.au > /dev/audio 2> /dev/null");
}

void change_style(void)
{
  GtkStyle *style;

  style=gtk_style_new();
  if(style->font) gdk_font_unref(style->font);
  style->font=gdk_font_load("-*-helvetica-medium-r-*-*-8-*-*-*-p-*-*-*");
  gtk_widget_set_default_style(style);
}

void goenc(void)
{
  int error;
  char *filename;
  char *word;

  filename = gtk_entry_get_text(GTK_ENTRY(filename_entry));
  word = gtk_entry_get_text(GTK_ENTRY(entry));
  gtk_widget_hide(sub_window);
  error = enc(filename, word, GUI);
}

void godec(void)
{
  int error;
  char *filename;
  char *word;

  filename = gtk_entry_get_text(GTK_ENTRY(filename_entry));
  word = gtk_entry_get_text(GTK_ENTRY(entry));
  gtk_widget_hide(sub_window);
  error = dec(filename, word, GUI);
}
