/*
 * Network Explorer
 *
 * Copyright (C) 1998, Mark Spencer
 * 
 * Distributed under the terms of the GNU GPL
 *
 */

#include <gtk/gtk.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
#include <sys/stat.h>
#include "cheops.h"

int option_automap=1;
int option_remember_positions=1;
int option_port_scan = 1;
int option_trim = 1;
int option_queso = 1;
int option_reverse_dns = 1;
int option_add_routes=0;
int option_use_icmp=0;
int option_use_visible_area=1;
int option_update_release=1;

static GtkWidget *options=NULL;
static GtkWidget *automap;
static GtkWidget *remember;
static GtkWidget *portscan;
static GtkWidget *trim;
static GtkWidget *queso;
static GtkWidget *revdns;
static GtkWidget *addroutes;
static GtkWidget *useicmp;
static GtkWidget *visible;
static GtkWidget *release;

static void cancel_options()
{
	if (!options) 
		return;
	gtk_widget_destroy(options);
	options=NULL;
}


static void change_int(GtkWidget *w, int *data)
{
	*data = !*data;
}

#define PREFS_LINK(a,b) { \
	gtk_widget_show(a); \
	if (b) \
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(a), TRUE); \
	else \
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(a), FALSE); \
	gtk_signal_connect(GTK_OBJECT(a), "clicked", GTK_SIGNAL_FUNC(change_int), &b); \
	gtk_box_pack_start(GTK_BOX(w), a, FALSE, FALSE, 0); \
} 

#define CHECK_OPT(a,b) { \
	if (!strcasecmp(opt,a)) \
		b = atoi(val); \
}
	

int load_options()
{
	char buf[256];
	char *h;
	char *opt, *val;
	FILE *f;
	if (!(h = getenv("HOME")))
		return -1;
	snprintf(buf, sizeof(buf), "%s/.cheops-options", getenv("HOME"));
	if (!(f=fopen(buf, "r")))
		return -1;
	while(!feof(f)) {
		fgets(buf, sizeof(buf), f);
		if (!feof(f)) {
			opt = strchr(buf, '[');
			if (!opt)
				continue;
			opt++;
			val = strchr(opt, ' ');
			if (!val)
				continue;
			*val='\0';
			val++;
			h = strchr(val,']');
			if (!h)
				continue;
			*h='\0';
			CHECK_OPT("automap",option_automap);
			CHECK_OPT("remember", option_remember_positions);
			CHECK_OPT("portscan", option_port_scan);
			CHECK_OPT("trim",option_trim);
			CHECK_OPT("queso", option_queso);
			CHECK_OPT("revdns", option_reverse_dns);
			CHECK_OPT("addroutes", option_add_routes); 			
			CHECK_OPT("useicmp", option_use_icmp);
			CHECK_OPT("release", option_update_release);
		}
	}
	fclose(f);
	return 0;
}

int save_options()
{
	char buf[256];
	char *h;
	FILE *f;
	if (!(h = getenv("HOME")))
		return -1;
	snprintf(buf, sizeof(buf), "%s/.cheops-options", getenv("HOME"));
	if (!(f=fopen(buf, "w")))
		return -1;
	fprintf(f,"[automap %d]\n", option_automap);
	fprintf(f,"[remember %d]\n", option_remember_positions);
	fprintf(f,"[portscan %d]\n", option_port_scan);
	fprintf(f,"[trim %d]\n", option_trim);
	fprintf(f,"[queso %d]\n", option_queso);
	fprintf(f,"[revdns %d]\n",option_reverse_dns);
	fprintf(f,"[addroutes %d]\n",option_add_routes);
	fprintf(f,"[useicmp %d]\n", option_use_icmp);
	fprintf(f,"[visible %d]\n", option_use_visible_area);
	fprintf(f,"[release %d]\n", option_update_release);
	fclose(f);
	if (options) {
		gtk_widget_destroy(options);
		options=NULL;
	}
	return 0;
}


static void make_prefs(GtkWidget *w)
{
	automap = gtk_check_button_new_with_label("Automatically map all hosts I add to a mapped page");
	remember = gtk_check_button_new_with_label("Remember where I put all the hosts that I've moved");
	trim = gtk_check_button_new_with_label("Trim hostnames when displaying them");
	queso = gtk_check_button_new_with_label("Determine the operating system of new hosts (queso)");
	portscan = gtk_check_button_new_with_label("Determine what services a host supports (half-scan)");
	revdns = gtk_check_button_new_with_label("Lookup hosts I add with reverse DNS");	
	addroutes = gtk_check_button_new_with_label("When I map a host, add all hosts on the map to the page");
	useicmp = gtk_check_button_new_with_label("Use ICMP instead of UDP for mapping");
	visible = gtk_check_button_new_with_label("Fill width in the area I see only");
	release = gtk_check_button_new_with_label("Only update the map drawing when I stop moving an object");

	PREFS_LINK(automap, option_automap);
	PREFS_LINK(remember, option_remember_positions);
	PREFS_LINK(portscan, option_port_scan);
	PREFS_LINK(trim, option_trim);
	PREFS_LINK(queso, option_queso);
	PREFS_LINK(revdns, option_reverse_dns);
	PREFS_LINK(addroutes, option_add_routes);
	PREFS_LINK(useicmp, option_use_icmp);
	PREFS_LINK(visible, option_use_visible_area);
	PREFS_LINK(release, option_update_release);
}

void show_options()
{
	GtkWidget *bbox;
	GtkWidget *vbox;
	GtkWidget *features;
	GtkWidget *notebook;
	GtkWidget *label;
	GtkWidget *sep;
	GtkWidget *close;
	GtkWidget *save;
	
	if (options) {
		gtk_widget_show(options);
		return;
	}
	/* Misc */
	sep = gtk_hseparator_new();
	gtk_widget_show(sep);

	/* Window and containers */
	options = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(options), "Options");

	notebook = gtk_notebook_new();
	gtk_widget_show(notebook);
	
	features = gtk_vbox_new(FALSE, 0);
	gtk_widget_show(features);
	
	make_prefs(features);
	
	label = gtk_label_new("Features");
	gtk_widget_show(label);
	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), features, label);

	vbox = gtk_vbox_new(FALSE, 5);
	bbox = gtk_hbox_new(FALSE, 5);
	gtk_widget_show(bbox);
	gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 5); 
	gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 5); 
	gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 5); 
	gtk_widget_show(vbox);
	

	/* Buttons */
	close = gtk_button_new_with_label("Close");
	save = gtk_button_new_with_label("Save");
	gtk_widget_show(close);
	gtk_widget_show(save);
	
	
	gtk_box_pack_end(GTK_BOX(bbox),close, FALSE, FALSE, 5);
	gtk_box_pack_end(GTK_BOX(bbox),save, FALSE, FALSE, 5);
	
	/* Signal handlers */
	gtk_signal_connect(GTK_OBJECT(save), "clicked", GTK_SIGNAL_FUNC(save_options), NULL);
	gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(cancel_options), NULL);
	gtk_signal_connect(GTK_OBJECT(options), "delete_event", GTK_SIGNAL_FUNC(cancel_options), NULL);
	
	gtk_container_add(GTK_CONTAINER(options), vbox);
	gtk_container_border_width(GTK_CONTAINER(options), 10);
	gtk_widget_grab_focus(close); 
	
	gtk_widget_show(options);	
	
}

static int file_exists(char *s)
{
	struct stat buf;
	if (stat(s, &buf) < 0)
		return 0;
	if (S_ISREG(buf.st_mode)) {
		return 1;
	}
	return 0;
	
}

char *find_file(char *s)
{
	static char *paths[] = {
#ifdef DEFAULT_PATH
		DEFAULT_PATH,
#endif
		"/usr/share/cheops",
		"/usr/local/share/cheops",
		"/usr/lib/cheops",
		"/usr/local/lib/cheops",
		"/etc/cheops",
		"/usr/local/etc/cheops",
		"pixmaps",
		".",
		NULL
	};
	static char buf[256];
	static char *e = NULL;
	int x;
	if (!e) 
		e = getenv("CHEOPS_HOME");
	if (e) {
		snprintf(buf, sizeof(buf), "%s/%s", e, s);
		if (file_exists(buf))
			return buf;
	}
	for (x=0; paths[x]; x++) {
		snprintf(buf, sizeof(buf), "%s/%s", paths[x], s);
		if (file_exists(buf))
			return buf;
	}
	fprintf(stderr, "Critical: Unable to find file '%s'...  Expect a crash soon!\n",s);
	return NULL;
}
