
/*  Gpasman, a password manager
    Copyright (C) 1998 Olivier Sessink, olivier@lx.student.wau.nl
	
	 website at http://www.student.wau.nl/~olivier/gpasman/

    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <gtk/gtk.h>
#include <glib.h>
#include <unistd.h>
#include <string.h>
#include <rc2.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>

#ifndef S_IAMB
#define S_IAMB 00777
#endif

	void button_add_clicked( GtkWidget *button, gpointer data);
	void button_clear_clicked( GtkWidget *button, gpointer data);
	void really_clear_list( GtkWidget *button, gpointer data);	
	void button_hide_show_clicked( GtkWidget *button, gpointer data);
	void selection_made( GtkWidget *clist, gint row, gint column,
                          GdkEventButton *event, gpointer data);
	void unselection_made( GtkWidget *clist, gint row, gint column,
                          GdkEventButton *event, gpointer data);
	void new_set_add( GtkWidget *button, gpointer data);
	void window_close( GtkWidget *button,  gpointer windowname) ;
	void quit_gpasman( GtkObject *object );
	void button_remove_clicked( GtkWidget *button, gpointer data);
	void save_all( GtkWidget *button, gpointer end);
	void openfile();
	void main_window ( GtkWidget *oldwindow, gpointer data);
	void close_startup( GtkWidget *oldwindow, gpointer data);
	void change_password( GtkWidget *button, gpointer data);
	void check_password( GtkWidget *button,  gpointer data);
	void warning_dialog(char *warningtext, char quit);
	int check_gpasfile(char* passfile);
	int file_exists(char* tfile);


GtkWidget *clist, *entry1, *entry2, *entry3, *entry4;
int selectedrow=-1, totalrows=0;
char password[30];
char naam[256];
char changed=0;
char end=1, noend=0;
			
gint main (int argc, gchar *argv[]) {                                  
   GtkWidget   *window;
   GtkWidget   *vbox;
   GtkWidget 	*button_ok;
   GtkWidget 	*label1;
   char HOME[5];
   

   gtk_init(&argc, &argv);
	
   strcat(strcpy(naam, getenv(strcpy(HOME, "HOME"))), "/.gpasman");
   if(file_exists(naam)) {
      warning_dialog("~/.gpasman does not exist, will create a new one", 0);
      create_gpasfile();
   }
   if(check_gpasfile(naam)) {
      warning_dialog("There is an error with your ~/.gpasman file, look at the stderr output", 1);
      gtk_main();
   } else {
   	window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_container_border_width (GTK_CONTAINER (window), 10);	
      gtk_widget_set_usize(GTK_WIDGET(window), 200, 150);
   	gtk_window_set_title(GTK_WINDOW(window), "Gpasman 1.0");
  	   vbox=gtk_vbox_new(FALSE, 5);
   	gtk_container_border_width(GTK_CONTAINER(vbox), 5);
   	gtk_container_add(GTK_CONTAINER(window), vbox);
   	gtk_widget_show(vbox);

		entry1 = gtk_entry_new_with_max_length (100);	
		gtk_entry_set_visibility( GTK_ENTRY(entry1),
										 '0');
		button_ok = gtk_button_new_with_label("Ok");
		label1 = gtk_label_new("Enter password");

		gtk_box_pack_start(GTK_BOX(vbox), label1, TRUE, TRUE, 3);	
		gtk_box_pack_start(GTK_BOX(vbox), entry1, TRUE, TRUE, 3);	
		gtk_box_pack_start(GTK_BOX(vbox), button_ok, TRUE, TRUE, 3);
	
	   gtk_signal_connect_object(GTK_OBJECT(button_ok), "clicked",
	                            GTK_SIGNAL_FUNC(main_window),
	                            (gpointer) window );
   	gtk_signal_connect_object(GTK_OBJECT(button_ok), "clicked",
                             GTK_SIGNAL_FUNC(close_startup),
                             (gpointer) window );
		gtk_signal_connect(GTK_OBJECT(window),
                            "destroy",
                            GTK_SIGNAL_FUNC(gtk_main_quit),
                            NULL);
   	gtk_signal_connect_object(GTK_OBJECT(entry1), "activate",
                             GTK_SIGNAL_FUNC(gtk_widget_grab_focus),
                             (gpointer) button_ok );									 
		gtk_widget_show(button_ok);
		gtk_widget_show(label1);
		gtk_widget_show(entry1);
	   gtk_widget_show(window);
		gtk_widget_grab_focus(entry1);
		gtk_main();         
	   return 0;
	}
}

void close_startup( GtkWidget *oldwindow, gpointer data) {
	gtk_signal_handlers_destroy((GtkObject*)data );
	gtk_object_destroy((GtkObject*)data );
}

void main_window ( GtkWidget *oldwindow, gpointer data) {
   GtkWidget       *window;
   GtkWidget       *vbox, *hbox1, *hbox2;
   GtkWidget       *button_add, *button_clear, *button_remove, *button_save, *button_exit, *button_chp;
   gchar           *titles[4] = {"Host", "Username", "Password", "Comment"};

                  
/* first make the entry1 ready for re-use */
   strcpy(password, gtk_entry_get_text(GTK_ENTRY(entry1)));
	gtk_object_destroy((GtkObject*)entry1);

	window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_usize(GTK_WIDGET(window), 600, 300);

	gtk_window_set_title(GTK_WINDOW(window), "Gpasman 1.0");
	gtk_signal_connect(GTK_OBJECT(window),
                            "destroy",
                            GTK_SIGNAL_FUNC(gtk_main_quit),
                            NULL);
         
	vbox=gtk_vbox_new(FALSE, 5);
	gtk_container_border_width(GTK_CONTAINER(vbox), 5);
	gtk_container_add(GTK_CONTAINER(window), vbox);
	gtk_widget_show(vbox);
         
         /* Create the GtkCList */
	clist = gtk_clist_new_with_titles( 4, titles);

	gtk_signal_connect(GTK_OBJECT(clist), "select_row",
                            GTK_SIGNAL_FUNC(selection_made),
                            NULL);
	gtk_signal_connect(GTK_OBJECT(clist), "unselect_row",
                            GTK_SIGNAL_FUNC(unselection_made),
                            NULL);									 

         /* It isn't necessary to shadow the border, but it looks nice :) */
	gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
	gtk_clist_set_column_width (GTK_CLIST(clist), 0, 200);
	gtk_clist_set_column_width (GTK_CLIST(clist), 1, 100);
	gtk_clist_set_column_width (GTK_CLIST(clist), 2, 100);
	gtk_clist_set_column_width (GTK_CLIST(clist), 3, 200);	

	/* Scollbars _only when needed_ */
	gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
                                                GTK_POLICY_AUTOMATIC);

	gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
	gtk_widget_show(clist);

	hbox1 = gtk_hbox_new(TRUE, 0);
	hbox2 = gtk_hbox_new(TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, TRUE, 0);
	gtk_widget_show(hbox1);
	gtk_widget_show(hbox2);

	button_add = gtk_button_new_with_label("Add");
	button_clear = gtk_button_new_with_label("Clear List");
	button_remove = gtk_button_new_with_label("Remove");
	button_save = gtk_button_new_with_label("Save");
	button_exit = gtk_button_new_with_label("Exit");
	button_chp = gtk_button_new_with_label("Change password");
	gtk_box_pack_start(GTK_BOX(hbox1), button_add, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(hbox1), button_remove, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(hbox1), button_clear, TRUE, TRUE, 0);	
   gtk_box_pack_start(GTK_BOX(hbox2), button_chp, TRUE, TRUE, 0);
   gtk_box_pack_start(GTK_BOX(hbox2), button_save, TRUE, TRUE, 0);
   gtk_box_pack_start(GTK_BOX(hbox2), button_exit, TRUE, TRUE, 0);

   gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
                                   GTK_SIGNAL_FUNC(button_add_clicked),
                                   (gpointer) clist);
   gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
                                   GTK_SIGNAL_FUNC(button_clear_clicked),
                                   (gpointer) clist);
   gtk_signal_connect_object(GTK_OBJECT(button_remove), "clicked",
                                   GTK_SIGNAL_FUNC(button_remove_clicked),
                                   (gpointer) clist);
   gtk_signal_connect_object(GTK_OBJECT(button_save), "clicked",
                                   GTK_SIGNAL_FUNC(save_all),
											  (gpointer) &noend );
   gtk_signal_connect_object(GTK_OBJECT(button_exit), "clicked",
                                   GTK_SIGNAL_FUNC(quit_gpasman),
											  (gpointer) window);
   gtk_signal_connect(GTK_OBJECT(button_chp), "clicked",
                                   GTK_SIGNAL_FUNC(change_password),
											  NULL);
											  
	gtk_widget_show(button_add);
	gtk_widget_show(button_clear);
   gtk_widget_show(button_remove);
   gtk_widget_show(button_save);
   gtk_widget_show(button_exit);
   gtk_widget_show(button_chp);
	gtk_widget_show(window);
	openfile();	
}

void quit_gpasman( GtkObject *object ) {
	GtkWidget *window, *label1, *button_ok, *button_cancel, *vbox, *hbox;

	if (changed) {
		window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_container_border_width (GTK_CONTAINER (window), 10);	
	 	gtk_grab_add(window); 
		gtk_window_position( GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
		gtk_window_set_title(GTK_WINDOW (window), "Really exit?");
	 	gtk_signal_connect (GTK_OBJECT (window), "delete_event",
	                            GTK_SIGNAL_FUNC(gtk_main_quit),
										 NULL);	 
		vbox = gtk_vbox_new (TRUE, 0);
		gtk_container_add (GTK_CONTAINER (window), vbox);
		gtk_widget_show (vbox);
		
		label1 = gtk_label_new("There is unsaved data, save?");	
		gtk_box_pack_start(GTK_BOX(vbox), label1, TRUE, TRUE, 0);	
		gtk_widget_show (label1);
		
		hbox = gtk_hbox_new (TRUE, 0);
		gtk_container_add (GTK_CONTAINER (vbox), hbox);
		gtk_widget_show (hbox);	
		
		button_ok = gtk_button_new_with_label("Save");
		button_cancel = gtk_button_new_with_label("Cancel");
		
		gtk_box_pack_start(GTK_BOX(hbox), button_ok, TRUE, TRUE, 0);
		gtk_widget_show (button_ok);			
		gtk_box_pack_start(GTK_BOX(hbox), button_cancel, TRUE, TRUE, 0);
		gtk_widget_show (button_cancel);	
			
	  	gtk_signal_connect_object (GTK_OBJECT (button_cancel), "clicked",
	                                    GTK_SIGNAL_FUNC(gtk_main_quit),
	                                    NULL ); 
		gtk_signal_connect_object (GTK_OBJECT (button_ok), "clicked",
	                                    GTK_SIGNAL_FUNC(save_all),
	                                    (gpointer) &end);
		gtk_widget_show (window);
	} else {
		gtk_main_quit();
	}
}
	  
void new_set_add( GtkWidget *button, gpointer data) {

	gchar *entry_text[4];
		 
	entry_text[0] = gtk_entry_get_text(GTK_ENTRY(entry1));
	entry_text[1] = gtk_entry_get_text(GTK_ENTRY(entry2));
	entry_text[2] = gtk_entry_get_text(GTK_ENTRY(entry3));
	entry_text[3] = gtk_entry_get_text(GTK_ENTRY(entry4));		 
	gtk_clist_append( (GtkCList*)clist, entry_text);
	totalrows++;
	changed=1;
	window_close(button, data); 
}

void window_close( GtkWidget *button,  gpointer windowname) {
	gtk_grab_remove(windowname );
	gtk_object_destroy((GtkObject *)windowname);
}
	  
void button_remove_clicked( GtkWidget *button, gpointer data) {
	if ( selectedrow != -1)	{
		gtk_clist_remove((GtkCList*) clist, selectedrow);
		totalrows--;
		changed=1;
	} else {
	   warning_dialog("There is no row selected", 0);
	}
}
	  
void button_add_clicked( GtkWidget *button, gpointer data) {
	GtkWidget *window;
   GtkWidget *vbox, *hbox;
   GtkWidget *button2, *button3;			
			
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_container_border_width (GTK_CONTAINER (window), 10);	
	gtk_grab_add(window);
	gtk_window_position( GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
	gtk_window_set_title(GTK_WINDOW (window), "Enter new account");
	gtk_signal_connect_object(GTK_OBJECT (window), "delete_event",
                            GTK_SIGNAL_FUNC(window_close),
									 (gpointer)window);

	vbox = gtk_vbox_new (TRUE, 0);
	gtk_container_add (GTK_CONTAINER (window), vbox);
	gtk_widget_show (vbox);

	entry1 = gtk_entry_new_with_max_length (100);
	gtk_entry_set_text (GTK_ENTRY (entry1), "server");
	entry2 = gtk_entry_new_with_max_length (50);
	gtk_entry_set_text (GTK_ENTRY (entry2), "username");			
	entry3 = gtk_entry_new_with_max_length (50);
	gtk_entry_set_text (GTK_ENTRY (entry3), "password");
	entry4 = gtk_entry_new_with_max_length (100);
	gtk_entry_set_text (GTK_ENTRY (entry4), "comment");
						
	gtk_box_pack_start (GTK_BOX (vbox), entry1, TRUE, TRUE, 0);
	gtk_widget_show (entry1);
	gtk_box_pack_start (GTK_BOX (vbox), entry2, TRUE, TRUE, 0);
	gtk_widget_show (entry2);			
	gtk_box_pack_start (GTK_BOX (vbox), entry3, TRUE, TRUE, 0);
	gtk_widget_show (entry3);
	gtk_box_pack_start (GTK_BOX (vbox), entry4, TRUE, TRUE, 0);
	gtk_widget_show (entry4);	
			
	hbox = gtk_hbox_new (TRUE, 0);
	gtk_container_add (GTK_CONTAINER (vbox), hbox);
	gtk_widget_show (hbox);
                                        
	button2 = gtk_button_new_with_label ("Cancel");
	button3 = gtk_button_new_with_label ("Add this account");
			
	gtk_signal_connect_object (GTK_OBJECT (button2), "clicked",
                                    GTK_SIGNAL_FUNC(window_close),
                                    (gpointer)window );
	gtk_signal_connect_object (GTK_OBJECT (button3), "clicked",
                                    GTK_SIGNAL_FUNC(new_set_add),
                                    (gpointer) window);
	gtk_box_pack_start (GTK_BOX (hbox), button2, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (hbox), button3, TRUE, TRUE, 0);

	gtk_widget_show (button2);
	gtk_widget_show (button3);
   gtk_widget_show(window);
}


void button_clear_clicked( GtkWidget *button, gpointer data) {
	GtkWidget *window;
	GtkWidget *label1;
	GtkWidget *button_ok, *button_cancel;
	GtkWidget *vbox, *hbox;

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_container_border_width (GTK_CONTAINER (window), 10);	
 	gtk_grab_add(window); 
	gtk_window_position( GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
	gtk_window_set_title(GTK_WINDOW (window), "Confirm clear");
 	gtk_signal_connect_object (GTK_OBJECT (window), "delete_event",
                            GTK_SIGNAL_FUNC(window_close),
									 (gpointer)window);	 

	vbox = gtk_vbox_new (TRUE, 0);
	gtk_container_add (GTK_CONTAINER (window), vbox);
	gtk_widget_show (vbox);
	
	label1 = gtk_label_new("Are you sure you want to clear all entries?");	
	gtk_box_pack_start(GTK_BOX(vbox), label1, TRUE, TRUE, 0);	
	gtk_widget_show (label1);
	
	hbox = gtk_hbox_new (TRUE, 0);
	gtk_container_add (GTK_CONTAINER (vbox), hbox);
	gtk_widget_show (hbox);	
	
	button_ok = gtk_button_new_with_label("Clear");
	button_cancel = gtk_button_new_with_label("Cancel");
	
	gtk_box_pack_start(GTK_BOX(hbox), button_ok, TRUE, TRUE, 0);
	gtk_widget_show (button_ok);			
	gtk_box_pack_start(GTK_BOX(hbox), button_cancel, TRUE, TRUE, 0);
	gtk_widget_show (button_cancel);	
		
  	gtk_signal_connect_object (GTK_OBJECT (button_cancel), "clicked",
                                    GTK_SIGNAL_FUNC(window_close),
                                    (gpointer)window ); 
	gtk_signal_connect_object (GTK_OBJECT (button_ok), "clicked",
                                    GTK_SIGNAL_FUNC(really_clear_list),
                                    (gpointer) data);
	gtk_signal_connect_object (GTK_OBJECT (button_ok), "clicked",
                                    GTK_SIGNAL_FUNC(window_close),
                                    (gpointer) window); 

	GTK_WIDGET_SET_FLAGS (button_ok, GTK_CAN_DEFAULT);
	GTK_WIDGET_SET_FLAGS (button_cancel, GTK_CAN_DEFAULT);
	
	gtk_widget_show (window);
}

void really_clear_list( GtkWidget *button, gpointer data) {
	gtk_clist_clear((GtkCList*) data);
	totalrows = 0;
	changed = 1;
	return;
}

void change_password( GtkWidget *button, gpointer data) {
	GtkWidget *window;
   GtkWidget *vbox, *hbox;
   GtkWidget *button2, *button3;			
	GtkWidget *label1, *label2, *label3, *label4;
			
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_container_border_width (GTK_CONTAINER (window), 10);
	gtk_grab_add(window);
	gtk_window_position( GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
	gtk_window_set_title(GTK_WINDOW (window), "Change password");
	gtk_signal_connect_object(GTK_OBJECT (window), "delete_event",
                            GTK_SIGNAL_FUNC(window_close),
									 (gpointer)window);
	vbox = gtk_vbox_new (FALSE, 0);
	gtk_container_add (GTK_CONTAINER (window), vbox);
	gtk_widget_show (vbox);

	label1 = gtk_label_new("Change Password");
	label2 = gtk_label_new("Enter old password");	
	entry1 = gtk_entry_new_with_max_length (25);
	gtk_entry_set_visibility(GTK_ENTRY(entry1), 0);
	gtk_entry_set_text (GTK_ENTRY (entry1), "");
	label3 = gtk_label_new("Enter new password");	
	entry2 = gtk_entry_new_with_max_length (25);
	gtk_entry_set_visibility(GTK_ENTRY(entry2), 0);
	gtk_entry_set_text (GTK_ENTRY (entry2), "");
	label4 = gtk_label_new("Confirm new password");
	entry3 = gtk_entry_new_with_max_length (25);
	gtk_entry_set_text (GTK_ENTRY (entry3), "");
	gtk_entry_set_visibility(GTK_ENTRY(entry3), 0);

	gtk_box_pack_start (GTK_BOX (vbox), label1, TRUE, TRUE, 5);
	gtk_widget_show (label1);
	gtk_box_pack_start (GTK_BOX (vbox), label2, FALSE, FALSE, 0);
	gtk_widget_show (label2);
	gtk_box_pack_start (GTK_BOX (vbox), entry1, FALSE, FALSE, 1);
	gtk_widget_show (entry1);
	gtk_box_pack_start (GTK_BOX (vbox), label3, FALSE, FALSE, 0);
	gtk_widget_show (label3);
	gtk_box_pack_start (GTK_BOX (vbox), entry2, FALSE, FALSE, 1);
	gtk_widget_show (entry2);
	gtk_box_pack_start (GTK_BOX (vbox), label4, FALSE, FALSE, 0);
	gtk_widget_show (label4);
	gtk_box_pack_start (GTK_BOX (vbox), entry3, FALSE, FALSE, 1);
	gtk_widget_show (entry3);
			
	hbox = gtk_hbox_new (TRUE, 0);
	gtk_container_add (GTK_CONTAINER (vbox), hbox);
	gtk_widget_show (hbox);
                                        
	button2 = gtk_button_new_with_label ("Cancel");
	button3 = gtk_button_new_with_label ("Ok");
			
	gtk_signal_connect_object (GTK_OBJECT (button2), "clicked",
                                    GTK_SIGNAL_FUNC(window_close),
                                    (gpointer)window );
	gtk_signal_connect_object (GTK_OBJECT (button3), "clicked",
                                    GTK_SIGNAL_FUNC(check_password),
                                    (gpointer) window);
	gtk_box_pack_start (GTK_BOX (hbox), button2, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (hbox), button3, TRUE, TRUE, 0);
			
	GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
	GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT);

	gtk_widget_show (button2);
	gtk_widget_show (button3);
   gtk_widget_show(window);
}

void warning_dialog(char *warningtext, char quit ) {
	GtkWidget *dialog, *label1, *button_ok;
	dialog = gtk_dialog_new ();
	gtk_window_position( GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);	
	button_ok = gtk_button_new_with_label ("Ok");
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button_ok,
                        TRUE, TRUE, 0);
	gtk_widget_show (button_ok);
	if (quit) {
		gtk_signal_connect (GTK_OBJECT (button_ok), "clicked",
                                   GTK_SIGNAL_FUNC(gtk_main_quit),
                                   NULL );
	} else {
		gtk_signal_connect_object (GTK_OBJECT (button_ok), "clicked",
                                   GTK_SIGNAL_FUNC(window_close),
                                   (gpointer)dialog );
	}
	label1 = gtk_label_new (warningtext);
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label1, TRUE,
                        TRUE, 0);
	gtk_widget_show (label1);
	gtk_widget_show (dialog);
}

void check_password( GtkWidget *button,  gpointer data) {

	char tmppass[30];

	strcpy(tmppass, gtk_entry_get_text(GTK_ENTRY(entry1)));
	if (strcmp(password, tmppass) != 0) {
		warning_dialog("Current password incorrect", 0);
		gtk_object_destroy((GtkObject*)data );
 		return; 
	}
	strcpy(tmppass, gtk_entry_get_text(GTK_ENTRY(entry2)));	
	if  (strcmp(tmppass, gtk_entry_get_text(GTK_ENTRY(entry3))) != 0) {
		warning_dialog("New passwords are not identical", 0);
		gtk_object_destroy((GtkObject*)data );
 		return; 
	}
   strcpy(password, gtk_entry_get_text(GTK_ENTRY(entry2)));
	changed = 1 ;
	gtk_object_destroy((GtkObject*)data );
}


void selection_made( GtkWidget *clist, gint row, gint column,
                          GdkEventButton *event, gpointer data) {
	selectedrow = row;
}
	  
void unselection_made( GtkWidget *clist, gint row, gint column,
                          GdkEventButton *event, gpointer data) {
	selectedrow = -1;
}
	  

void save_all( GtkWidget *button, gpointer end) {

	gchar *text1;
	int count1, count2;
	unsigned int i,j=0, keylength;
	unsigned char key[128];
	char buffer[1024], HOME[5], naam[256];
	unsigned char charbuf[8];
	unsigned short text[4];	
	FILE *outfile;
		
/* open the outfile (needs better error handling */

   strcat(strcpy(naam, getenv(strcpy(HOME, "HOME"))), "/.gpasman");
	outfile = fopen(naam, "wb");
	if (outfile == NULL) {
		warning_dialog("Could not open ~/.gpasman for writing", 0);
		return;
	}

/* make the key ready */
	for (j = 0; password[j] != '\0'; j++) {
		key[j] = password[j];
	}	
	keylength = j;	
	rc2_expandkey((char*)key, keylength, 128);	
	
/* read the clist into the buffer*/
	for( count1=0 ; count1<totalrows ; count1++ ) {
/*  create a random buffer content */
	   buffer[0] = '\0';
		srand(key[2]);
		for (count2=1 ; count2< 1024; count2++) {
		   buffer[count2] = rand();
		}
		for (count2=0 ; count2<4 ; count2++ ) {
			gtk_clist_get_text(GTK_CLIST(clist), count1, count2, &text1);
			strcat(buffer, text1);
			strcat(buffer, "\n");
			}

/* encrypt the buffer and write to file */		
		for (count2=0; count2<128; count2++) {
			for (i=0; i<8;i++) {
				charbuf[i] = buffer[i +8*count2];
				}
			for (i = 0; i < 4; i++) {
				text[i] = charbuf[i * 2] + 256 * charbuf[i * 2 + 1];
			}
			rc2_encrypt(text);
			for (i = 0; i < 4; i++) {
				charbuf[i * 2] = text[i] & 0xff;
				charbuf[i * 2 + 1] = text[i] >> 8;
			}
			for (i = 0; i < 8; i++) {
				putc((int) charbuf[i], outfile);
			}
		}
	}
	fclose(outfile);
	changed = 0;
	if ( *(char *)end) {
		gtk_main_quit();
	}
}	  

void openfile() {
	char HOME[5];
	int count1, count2, count3, count4;
	char buffer[1024], server[300],username[100],passw[100],comment[450], naam[256];
   gchar *entry_text[4];
	unsigned int i,j=0, keylength;
	unsigned char key[128];	
	FILE *infile;
	unsigned char charbuf[8];
	unsigned short text[4];
	unsigned int count;	
		
	strcat(strcpy(naam, getenv(strcpy(HOME, "HOME"))), "/.gpasman");
/* allocate memory for entry_text */
	entry_text[0]=server;
	entry_text[1]=username;
	entry_text[2]=passw;	
	entry_text[3]=comment;		

/* open the infile (needs better error handling) */
	infile = fopen(naam, "rb");
	if (infile == NULL) {
		warning_dialog("Could not open ~/.gpasman for reading", 0);
		return;
	}
	
/* make the key ready */
	for (j = 0; password[j] != '\0'; j++) {
		key[j] = password[j];
	}
	keylength = j;	
	rc2_expandkey((char*)key, keylength, 128);	
	
	count1 = count3 = count4 = 0;
	memset(buffer, '\0', sizeof(buffer));	
		
	do {
		count = read(fileno(infile),charbuf,8);
		if (count == 0) {
		} else {
			if (count < 8) {
				for (i = count; i < 8; i++) {
					charbuf[i] = '\0';
				}
			}
			for (i = 0; i < 4; i++) {
				text[i] = charbuf[i * 2] + 256 * charbuf[i * 2 + 1];
			}
			rc2_decrypt(text);
			for (i = 0; i < 4; i++) {
				charbuf[i * 2] = text[i] & 0xff;
				charbuf[i * 2 + 1] = text[i] >> 8;
			}
			for (i = 0; i < 8; i++) {
				buffer[i + 8*count1] = charbuf[i];
			}
			count1++;		
			if (count1 == 128) {
				for (count2=0 ; count2<1024 ; count2++) {
					if (count3 < 4) {
						if ( buffer[count2] == '\n') {
							entry_text[count3][count4] = 	'\0';
							count3++;
							count4 = 0;
						} else {
							entry_text[count3][count4] = 	buffer[count2];
							count4++;
						}
					}
				}
				gtk_clist_append( (GtkCList*)clist, entry_text);
				totalrows++;
				memset(buffer, '\0', sizeof(buffer));
				count3 = 0;
				count4 = 0;
				count1 = 0;
			}
		}
	} while (count == 8);
	fclose(infile);
	changed = 0;
}

int check_gpasfile(char* passfile) {
  struct stat naamstat;

  if(stat(passfile, &naamstat) == -1) {
    perror("gpasman, lstat returned -1");
  }

  if(( (naamstat.st_mode & S_IAMB) | (S_IRUSR | S_IWUSR)) != (S_IRUSR | S_IWUSR)) { 

/*     warning_dialog("~/.gpasman permissions are bad"); */
    fprintf(stderr, "~/.gpasman perms are bad, they are: %d, should be -rw------\n", (naamstat.st_mode & (S_IREAD | S_IWRITE)));
    return(1);
  }
  
  if( !S_ISREG(naamstat.st_mode) ) {
    lstat(passfile, &naamstat);
    if(S_ISLNK(naamstat.st_mode)) {
/*       warning_dialog("~/.gpasman is a symbolic link"); */
      fprintf(stderr, "~/.gpasman is a symlink\n");
      
      return(1);
    }
  }

  return(0);
  
}

int file_exists(char* tfile) {
  struct stat naamstat;

  if((stat(tfile, &naamstat) == -1) && (errno == ENOENT)) {
    return(1);
  } else {
    return(0);
  }
}

int create_gpasfile() {
  mode_t oldumask;
  int ret;
  
  oldumask = umask(0);
  
  ret = creat(naam, (S_IRUSR | S_IWUSR));
  umask(oldumask);
  return(ret);
}
