#!/usr/bin/perl -w
#
#   GUI interface for wicrawl
#
#   wicrawl - A modular and thorough wi-fi scanner
#   http://midnightresearch.com/projects/wicrawl - for details
#
#   Original Code:  Peter Kacherginsky (cybernmd)
#   Contributors:  Aaron Peterson
#   $Id: wicrawl-gtk,v 1.46 2006/09/29 15:32:11 sith Exp $
#
#   Copyright (C) 2005-2006 Midnight Research Laboratories
#
#   THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTY IS ASSUMED.
#   NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
#   FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED. IT CAN BURN
#   YOUR HARD DISK, ERASE ALL YOUR DATA AND BREAK DOWN YOUR
#   MICROWAVE OVEN. YOU ARE ADVISED.
#
#   wicrawl 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.  For details see doc/LICENSE.


use strict;
use File::Basename;
use IO::Pipe;
use XML::Smart;
use FileHandle;
use POSIX ":sys_wait_h";

use Gtk2 -init;
use Glib qw(TRUE FALSE);
use Gtk2::SimpleList;
use Gtk2::Helper;

use MIME::Base64;

# AUTOFLUSH
#$|=1;tim

my $window; #overall gui window

my $buffer;
my $basedir;
my $cutroot = 1;
my $confdir="/etc/wicrawl";
my $profiledir="$basedir/profiles";
my $plugindir="$basedir/plugins";
my $wicrawl = "$basedir/plugins/plugin-engine";
my $outputdir="/var/log/wicrawl";
my $apcoredb;
my $plugincoredb;
my $runtime;
my $slist;
my $button;
my $helper_tag;
my $aps_timeout;

my $t_start_button;
my $wicrawl_menu_start;
my $wicrawl_menu_stop;


my $menu_bar; # top menu bar

# top menu tabs

my $tabs_menu;

#filter ssid
my $filter;
my $entry;

#used for detection of interfaces
my %interface;
my $monitor_interface;

#profiles
my $default_profile="default";
my $default_scheduling="first";
my $profileext=".conf";
my $profile;
my @card_scheduling = qw/first active signal all/;
my @plugins;
my @runlengths = qw/short medium long/;
my @profiles;
my @themes;
my $cb;
my $wicrawl_menu_profile;

#plugins
my $pluginext="plugin.conf";
my $current_plugin;
my $default_plugin="iwconfig_associate";
my @events = qw/new-ap associated have-ip have-internet/;

my $tree_view;


# Set basedir here so we can set the lib path dynamically.
BEGIN { 
	$basedir="@@BASEDIR@@/";
}

#open a pipe to a command
my $fh;
my $pid;

#menu edit
my $hb;
my $nb;
my $frame;

my $apsw;
my $pluginsw;

#ap information
my $ap_tree_store;
my $ap_tree_view;

#plugin information
my $tree_store;

#toolbar
my $aligners;

my $t_infobar;
my $infobar_buffer;

my $newap_bar;
my $associated_bar;
my $ip_bar;
my $internet_bar;

my $colorbar;

my $image;

my $image_dir = "$basedir/ui/pix";


#Preferences
use lib "$basedir/include/perl/";
use Preferences;
use AccessPoint;
use Profile;
use Plugin;

# External module included with wicrawl from cpan
use Text::TabularDisplay;


# Check to make sure that the effective user id is 0
if($> != 0) {
	print "\n [!!] Sorry you need to be root to run this\n";
	exit 1;
}

#######################################################################
# User Interface Section
#
###################

# This will be used for themes later

# Standard window creation, placement, and signal connecting
$window = Gtk2::Window->new('toplevel');
$window->signal_connect('delete_event' => sub {
	#cleanup before exiting


				if($pid) {
					kill(2, $pid);
					my $kid=waitpid($pid, WNOHANG);
					if($kid <= 0) {
						waitpid($pid, 0);
					}
					lprint(0,3, "Child [$pid] dead\n");
					lprint(1,1, "Discovery and plugin-engine finished\n");
		
					close($fh);
				}

				Gtk2->main_quit; 
});
$window->set_border_width(5);
$window->set_position('center_always');
$window->set_icon_from_file("$basedir/ui/pix/Mrl.jpg");

# This vbox will return the bulk of the gui
my $vbox = &ret_vbox();

# Hack Warning: Hiding some buttons/tabs/etc on startup
$wicrawl_menu_stop->hide_all;
#$nb->remove($profile);


# Hack Warning: hide infobar on startup
$t_infobar->hide_all;

# Add and show the vbox
$window->add($vbox);
$window->show();

# Set default theme

my $preferences = &get_preferences;
if($preferences->theme ne "default") {
	my $theme = $preferences->theme;
	Gtk2::Rc->parse("$basedir/ui/themes/$theme/gtk-2.0/gtkrc");
}
#$verbosity = $preferences->verbosity_ui;

my $warn=" [!!!] Wicrawl is a tool intended for security professionals, Please\n";
$warn.="act responsibly.  Use the SSID filters to scan only devices you control [!!!]\n\n";
lprint(2,1, $warn);

if(!%interface) {
	my $msg="No wireless interfaces found\n";
	$msg.="\tMaybe you need to bring them up?\n";
	$msg.="\t(hint: \"ifconfig ath0 up\" or similar and restart)\n";
	lprint(2,1,$msg);
}

# Our main event-loop
Gtk2->main();

#######################################################################
# Testing stuff


#######################################################################
# function ret_vbox - Takes care of the GUI generation
#	Arguments: none
#		Returns: VBox
###################

sub ret_vbox {
	# prep some data
	&get_profiles;
	&get_interfaces;
	&find_plugins;
	&find_themes;


	# TODO: temp solution

	# main VBox container
	$vbox = Gtk2::VBox->new(FALSE,0);

#######################################################################
# Top Menu
#
		$menu_bar = Gtk2::MenuBar->new;
		$menu_bar->set_border_width(0);

		# Menu Bar data declaration

			# Top Menu - File
			my $menu_item_file = Gtk2::MenuItem->new('_File');

				my $file_menu = Gtk2::Menu->new();

					# New Profile Menu Item
					my $file_menu_profile = Gtk2::MenuItem->new_with_mnemonic("_New Profile...");
					$file_menu_profile->signal_connect('activate' => sub {
							$default_profile = "New";
							&profile_tab;
					});
					$file_menu->append($file_menu_profile);

					# Open Menu Item
					my $file_menu_open = Gtk2::MenuItem->new_with_mnemonic("_Open...");
					$file_menu_open->signal_connect('activate' => sub {
						&open_output;
					});
					$file_menu->append($file_menu_open);

					# Save Menu Item
					my $file_menu_save = Gtk2::MenuItem->new_with_mnemonic("_Save...");
					$file_menu_save->signal_connect('activate' => sub {
						&save_output('xml');
					});
					$file_menu->append($file_menu_save);


					# Exit Menu Item
					my $file_menu_exit = Gtk2::MenuItem->new_with_mnemonic("_Exit");
					$file_menu_exit->signal_connect('activate' => sub {
						#cleanup before exiting

						my $exit = show_message_dialog( $window, 'question',
													'Are you sure you want to exit?',
													'yes-no'
											);
						if($exit eq "yes") {
							if($pid) {
								kill(2, $pid);
								my $kid=waitpid($pid, WNOHANG);
								if($kid <= 0) {
								waitpid($pid, 0);
							}
							lprint(0,3, "Child [$pid] dead\n");
							lprint(1,1, "Discovery and plugin-engine finished\n");
		
							close($fh);
						}
						Gtk2->main_quit; 
						}
					});
					$file_menu->append($file_menu_exit);

					
				$menu_item_file->set_submenu($file_menu);
			
			$menu_bar->append($menu_item_file);

			# Top Menu - Edit
			my $menu_item_edit = Gtk2::MenuItem->new('_Edit');

				my $edit_menu = Gtk2::Menu->new();

					# New Profile Menu Itemget
					my $edit_menu_profile = Gtk2::MenuItem->new_with_mnemonic("_Edit Profile");

						my $edit_menu_profile_submenu = Gtk2::Menu->new();

						foreach (sort @profiles) {
							my $label = $_;
							my $profile = $_;
							$profile = Gtk2::MenuItem->new_with_label("$_");
							$profile->signal_connect('activate' => sub { 
								$default_profile = $label; 
								&profile_tab;
							});
							$edit_menu_profile_submenu->append($profile);	
						}

						$edit_menu_profile->set_submenu($edit_menu_profile_submenu);

					$edit_menu->append($edit_menu_profile);

					# New Plugin Menu Item
					my $edit_menu_plugin = Gtk2::MenuItem->new_with_mnemonic("Edit _Plugin");

						my $edit_menu_plugin_submenu = Gtk2::Menu->new();

						foreach (sort @plugins) {
							my $label = $_;
							my $plugin = $_;
							$plugin = Gtk2::MenuItem->new_with_label("$_");
							$plugin->signal_connect('activate' => sub { 
								$default_plugin = $label; 
								&plugin_tab;
							});
							$edit_menu_plugin_submenu->append($plugin);	
						}

						$edit_menu_plugin->set_submenu($edit_menu_plugin_submenu);

					$edit_menu->append($edit_menu_plugin);


					# Preferences Menu Item
					my $edit_menu_preferences = Gtk2::MenuItem->new_with_mnemonic("Preferences...");
					$edit_menu_preferences->signal_connect('activate' => sub { 
								&preferences_tab;
							});
					$edit_menu->append($edit_menu_preferences);


					
				$menu_item_edit->set_submenu($edit_menu);

			$menu_bar->append($menu_item_edit);

			# Top Menu - View
			my $menu_item_view = Gtk2::MenuItem->new('_View');

				my $view_menu = Gtk2::Menu->new();

					# Add a separator
					$view_menu->append(Gtk2::SeparatorMenuItem->new());	

					# Toolbar Menu Item
					my $view_menu_toolbar = Gtk2::CheckMenuItem->new_with_mnemonic("_Toolbar");
					$view_menu_toolbar->set_active(TRUE);
					$view_menu_toolbar->signal_connect('toggled' => sub {
						if($view_menu_toolbar->get_active) {
							$hb->show_all;
						} else {
							$hb->hide_all;
						}	
					});
					$view_menu->append($view_menu_toolbar);

					# Statusbar Menu Item
					my $view_menu_information = Gtk2::CheckMenuItem->new_with_mnemonic("_Information");
					$view_menu_information->set_active(TRUE);
					$view_menu_information->signal_connect('toggled' => sub {
						if($view_menu_information->get_active) {
							$nb->show_all;
						} else {
							$nb->hide_all;
						}				
					});
					$view_menu->append($view_menu_information);
					
					# Output Menu Item
					my $view_menu_output = Gtk2::CheckMenuItem->new_with_mnemonic("_Output");
					$view_menu_output->set_active(TRUE);
					$view_menu_output->signal_connect('toggled' => sub {
						if($view_menu_output->get_active) {
							$frame->show_all;
						} else {
							$frame->hide_all;
						}	
					});
					$view_menu->append($view_menu_output);

					# Add a separator
					$view_menu->append(Gtk2::SeparatorMenuItem->new());	
			
	
					# Ap Information Menu Item
					my $view_menu_ap = Gtk2::CheckMenuItem->new_with_mnemonic("_AP Information");
					$view_menu_ap->set_active(TRUE);
					$view_menu_ap->signal_connect('toggled' => sub {
						if($view_menu_ap->get_active) {
							$apsw->show_all;
						} else {
							$apsw->hide_all;
						}	
					});
					$view_menu->append($view_menu_ap);
	
					# Plugin Information Menu Item
					my $view_menu_plugin = Gtk2::CheckMenuItem->new_with_mnemonic("_Plugin Information");
					$view_menu_plugin->set_active(TRUE);
					$view_menu_plugin->signal_connect('toggled' => sub {
						if($view_menu_plugin->get_active) {
							$pluginsw->show_all;
						} else {
							$pluginsw->hide_all;
						}				
					});
					$view_menu->append($view_menu_plugin);
					
   					# Add a separator
					$view_menu->append(Gtk2::SeparatorMenuItem->new());					

				$menu_item_view->set_submenu($view_menu);

			$menu_bar->append($menu_item_view);
						

			# Top Menu - Wicrawl
			my $menu_item_wicrawl = Gtk2::MenuItem->new('_Wicrawl');

				my $wicrawl_menu = Gtk2::Menu->new();

					# Start Menu Item
					$wicrawl_menu_start = Gtk2::MenuItem->new_with_mnemonic("_Start");
					$wicrawl_menu_start->signal_connect('activate' => sub {
							&start_button;
					});
					$wicrawl_menu->append($wicrawl_menu_start);

					# Stop Menu Item
					$wicrawl_menu_stop = Gtk2::MenuItem->new_with_mnemonic("S_top");
					$wicrawl_menu_stop->signal_connect('activate' => sub {
							&start_button;
					});
					$wicrawl_menu->append($wicrawl_menu_stop);

					# TODO: make stop button hidden at first 

					# Add a separator
					$wicrawl_menu->append(Gtk2::SeparatorMenuItem->new());

					# SSID Menu Item
					my $wicrawl_menu_filter = Gtk2::MenuItem->new_with_mnemonic("Set SSID _Filter");
					$wicrawl_menu_filter->signal_connect('activate' => sub {

						my $ssid_dialog = Gtk2::Dialog->new('SSID Filter', $window,'destroy-with-parent',
															'gtk-ok' => 'none');

						my $filter_label = Gtk2::Label->new("Please enter SSID filter\n ie \"linksys\"");
						$ssid_dialog->vbox->add($filter_label);

						$entry = Gtk2::Entry->new();
						$ssid_dialog->vbox->add($entry);


						$ssid_dialog->signal_connect (response => sub { $_[0]->destroy });
						$ssid_dialog->show_all;
					});
					$wicrawl_menu->append($wicrawl_menu_filter);

					# Select Profile Menu Item
					my $wicrawl_menu_profile = Gtk2::MenuItem->new("Select _Profile");

						my $wicrawl_menu_profile_submenu = Gtk2::Menu->new();

						my $profile_group;

						foreach (sort @profiles) {
							my $label = $_;
							my $profile = $_;
							$profile = Gtk2::RadioMenuItem->new($profile_group, "$_");
							$profile->signal_connect('toggled' => sub { $default_profile = $label });
							$profile_group = $profile->get_group;
							$wicrawl_menu_profile_submenu->append($profile);	
						}

					
			$wicrawl_menu_profile->set_submenu($wicrawl_menu_profile_submenu);

					$wicrawl_menu->append($wicrawl_menu_profile);

					# Select Interface Menu Item
					my $wicrawl_menu_interface = Gtk2::MenuItem->new("Select _Interface");

						my $wicrawl_menu_interface_submenu = Gtk2::Menu->new();
	
						# check if there are any wireless interfaces available
						if(!%interface) {
							my $interface = Gtk2::CheckMenuItem->new("None");
							$wicrawl_menu_interface_submenu->append($interface);	
						}
						else {
						
							$wicrawl_menu_interface_submenu->append(Gtk2::MenuItem->new_with_label ('Use Interfaces'));
							$wicrawl_menu_interface_submenu->append(Gtk2::SeparatorMenuItem->new);
				
							foreach (sort keys %interface) {
								my $label = $_;
								my $interface = Gtk2::CheckMenuItem->new("$label");
								$interface->signal_connect('toggled' => sub {
									my $self = shift;			
									if ($self->get_active) {
										$interface{$label} = 1;
									} else {
										$interface{$label} = 0;
									}
								});
								$wicrawl_menu_interface_submenu->append($interface);	
							}
							$wicrawl_menu_interface_submenu->append(Gtk2::MenuItem->new_with_label (''));
							$wicrawl_menu_interface_submenu->append(Gtk2::MenuItem->new_with_label ('Monitor Mode'));
							$wicrawl_menu_interface_submenu->append(Gtk2::SeparatorMenuItem->new);
							
							my $interface_group;
							my $active = 1;

			  			foreach (sort keys %interface) {
			  			  my $label = $_;
				  			my $interface = Gtk2::RadioMenuItem->new($interface_group, "$_");
				  			# Set the first interface found as monitor interface
				  			if($active) {
				  			  $monitor_interface = $label;
				  			  $active = 0;
				  		  }
				  			$interface->signal_connect('toggled' => sub { $monitor_interface = $label });
				  			$interface_group = $interface->get_group;
				  			$wicrawl_menu_interface_submenu->append($interface);	
				  		}
						
						}

						$wicrawl_menu_interface->set_submenu($wicrawl_menu_interface_submenu);

					$wicrawl_menu->append($wicrawl_menu_interface);


					# New Plugin Menu Item
					my $wicrawl_menu_plugin = Gtk2::MenuItem->new_with_mnemonic("Run _Plugin");

						my $wicrawl_menu_plugin_submenu = Gtk2::Menu->new();

						foreach (sort @plugins) {
							my $label = $_;
							my $plugin = Gtk2::MenuItem->new_with_label("$label");
							$plugin->signal_connect('activate' => sub { 
								&run_plugin($label);
							});
							$wicrawl_menu_plugin_submenu->append($plugin);	
						}

						$wicrawl_menu_plugin->set_submenu($wicrawl_menu_plugin_submenu);

					$wicrawl_menu->append($wicrawl_menu_plugin);



				$menu_item_wicrawl->set_submenu($wicrawl_menu);

			$menu_bar->append($menu_item_wicrawl);

			# Top Menu - Tabs
			my $menu_item_tabs = Gtk2::MenuItem->new('_Tabs');

				$tabs_menu = Gtk2::Menu->new();

					# Ap Information Menu Item
					my $tabs_menu_ap = Gtk2::MenuItem->new_with_mnemonic("_AP Information");
					$tabs_menu_ap->signal_connect('activate' => sub {
						$nb->set_current_page($nb->page_num($apsw));
					});
					$tabs_menu->append($tabs_menu_ap);

					# Statusbar Menu Item
					my $tabs_menu_plugin = Gtk2::MenuItem->new_with_mnemonic("_Plugin Information");
					$tabs_menu_plugin->signal_connect('activate' => sub {
						$nb->set_current_page($nb->page_num($pluginsw));
					});
					$tabs_menu->append($tabs_menu_plugin);

					# Add a separator
					$tabs_menu->append(Gtk2::SeparatorMenuItem->new());					

				$menu_item_tabs->set_submenu($tabs_menu);

			$menu_bar->append($menu_item_tabs);


			# Top Menu - Help
			my $menu_item_help = Gtk2::MenuItem->new('_Help');
			$menu_item_help->set_right_justified(TRUE);

				my $help_menu = Gtk2::Menu->new();

					# Help Menu Item
					my $help_menu_content = Gtk2::ImageMenuItem->new_from_stock('gtk-help',undef);
					$help_menu_content->signal_connect('activate' => sub {print "selected content\n"});
					$help_menu->append($help_menu_content);			
		
					$help_menu->append(Gtk2::SeparatorMenuItem->new());
		
					# About Menu Item
					my $help_menu_about = Gtk2::ImageMenuItem->new_from_stock('gtk-about',undef);
					$help_menu_about->signal_connect('activate' => sub {
						my $about_dialog = Gtk2::Dialog->new('About', $window,'destroy-with-parent',
															'gtk-ok' => 'none');
						my $mrl_logo = Gtk2::Image->new_from_file("$basedir/ui/pix/Mrl_Big.jpg");
						$about_dialog->vbox->add($mrl_logo);

            my $label = Gtk2::Label->new;
            $label->set_markup("<span><b>
    o Aaron Peterson - Project Manager and Developer\n
    o Jason Spence - Developer\n
    o Peter Kacherginsky - Developer\n
    o Brian Johnson - Developer\n
</b></span>");
            $about_dialog->vbox->add($label);

						$about_dialog->signal_connect (response => sub { $_[0]->destroy });
						$about_dialog->show_all;


					});
					$help_menu->append($help_menu_about);

				$menu_item_help->set_submenu($help_menu);

			$menu_bar->append($menu_item_help);

		$vbox->pack_start($menu_bar,FALSE,FALSE,0);

#######################################################################
# Toolbar
#

		# The Handle box helps in creating a detachable toolbar
		$hb = Gtk2::HandleBox->new;

		# Create a Toolbar and do some initial settings
		my $toolbar = Gtk2::Toolbar->new;
		$toolbar->set_icon_size ('large-toolbar');
		$toolbar->set_show_arrow(FALSE);

		# Tooltips
		my $tt = Gtk2::Tooltips->new();

		# Start button
		$t_start_button = Gtk2::ToolButton->new_from_stock('gtk-execute');
		$t_start_button->set_label ('Start');
		$t_start_button->set_tooltip ($tt, "Start Wicrawl", "");
		$t_start_button->signal_connect('clicked' => sub {&start_button});
		$toolbar->insert($t_start_button,-1);

		# Minimized view

		# TextView window
		$t_infobar = Gtk2::ToolItem->new;
		my $frame = Gtk2::Frame->new;
		my $infobox = Gtk2::VBox->new;	


			$infobar_buffer = Gtk2::Label->new();
			$infobar_buffer->set_markup("<span size='x-large'>warbar</span>\n");
			$infobar_buffer->set_justify('center');
			$infobox->pack_start($infobar_buffer,FALSE,FALSE,0);		



		##################### SITHBAR ########################
		$colorbar = Gtk2::Label->new();
		$colorbar->set_justify('fill');

		my $colorbar_setup = "<span background='black'>";

		my $width = 143;
		for(my $i=0; $i < $width; $i++) { 
			$colorbar_setup .= " ";
		}

		$colorbar_setup .= "</span>";

		$colorbar->set_markup($colorbar_setup);


		$infobox->pack_start($colorbar,FALSE,FALSE,0);

		$frame->add($infobox);	
		$t_infobar->add($frame);
		$toolbar->insert($t_infobar,-1);	

		# Run Plugin button
		my $t_plugin_button = Gtk2::MenuToolButton->new_from_stock('gtk-execute');
		$t_plugin_button->set_label('Plugins');
		$t_plugin_button->set_menu($wicrawl_menu_plugin_submenu);
		$t_plugin_button->signal_connect('clicked' => sub {lprint(0,3,"Please select from the drop down menu on the right!\n")});
		$toolbar->insert($t_plugin_button,-1);

		# Separator
		my $t_separator1 = Gtk2::SeparatorToolItem->new;
		$toolbar->insert($t_separator1,-1);

		# Select Interface button
		my $t_interface_button = Gtk2::MenuToolButton->new_from_stock('gtk-preferences');
		$t_interface_button->set_label('Interfaces');
		$t_interface_button->set_menu($wicrawl_menu_interface_submenu);
		$t_interface_button->signal_connect('clicked' => sub {lprint(0,3,"Please select from the drop down menu on the right\n")});
		$toolbar->insert($t_interface_button,-1);

		# Select profile button
		my $t_profile_button = Gtk2::MenuToolButton->new_from_stock('gtk-preferences');
		$t_profile_button->set_label('Profiles');
		$t_profile_button->set_menu($wicrawl_menu_profile_submenu);
		$t_profile_button->signal_connect('clicked' => sub {lprint(0,3,"Please select from the drop down menu on the right\n")});
		$toolbar->insert($t_profile_button,-1);

		# Separator
		my $t_separator2 = Gtk2::SeparatorToolItem->new;
		$toolbar->insert($t_separator2,-1);

		# SSID Filter
		my $t_filter = Gtk2::ToolItem->new;
				
				my $filter_vbox = Gtk2::VBox->new();		

				my $filter_label = Gtk2::Label->new("SSID Filter");
				$filter_vbox->pack_start($filter_label,FALSE,FALSE,0);

				$entry = Gtk2::Entry->new();

				$filter_vbox->pack_start($entry,FALSE,FALSE,0);		

				$t_filter->add($filter_vbox);

		$toolbar->insert($t_filter,-1);

		# Separator
		my $t_separator3 = Gtk2::SeparatorToolItem->new;
		$toolbar->insert($t_separator3,-1);


		# Minimize button
		my $t_mini_button = Gtk2::ToolButton->new_from_stock('gtk-convert');
		$t_mini_button->set_label('Minimize');
		#$t_mini_button->set_right_justified(TRUE);
		$t_mini_button->signal_connect('clicked' => sub {
			if($t_mini_button->get_label eq "Minimize") {
				$t_mini_button->set_label('Maximize');
				#hide windows
				$nb->hide_all;
				$frame->hide_all;
				$menu_bar->hide_all;

				#hide buttons
				$t_plugin_button->hide_all;
				$t_interface_button->hide_all;
				$t_profile_button->hide_all;
				$t_filter->hide_all;

				#hide separators
				$t_separator1->hide_all;
				$t_separator2->hide_all;
				$t_separator3->hide_all;

				#show infobar output
				$t_infobar->show_all;

				$window->resize(800,60);
			}
			else {
				$t_mini_button->set_label('Minimize');
				#show windows
				$nb->show_all;
				$frame->show_all;
				$menu_bar->show_all;

				#show buttons
				$t_plugin_button->show_all;
				$t_interface_button->show_all;
				$t_profile_button->show_all;
				$t_filter->show_all;

				#hide separators
				$t_separator1->show_all;
				$t_separator2->show_all;
				$t_separator3->show_all;

				$t_infobar->hide_all;		

				$window->resize(800,600);
			}
		});
		$toolbar->insert($t_mini_button,-1);


		#create self-expanding spacing
		my $spacing = Gtk2::SeparatorToolItem->new;
		$spacing->set_draw(FALSE);
		$spacing->set_expand(TRUE);
		$toolbar->insert($spacing,-1);

		

		# wicrawl logo
		my $image_toolitem = Gtk2::ToolItem->new;
		$image = Gtk2::Image->new;
		$image->set_from_file("$image_dir/Mrl.jpg");
		$image_toolitem->add($image);
		$toolbar->insert($image_toolitem,-1);

		$hb->add($toolbar);

		$vbox->pack_start($hb, FALSE, FALSE, 0);		

	# Information Tabs
	$nb = Gtk2::Notebook->new;
	$nb->set_scrollable(TRUE);
   	$nb->popup_enable;

		############# AP INFORMATION TAB ##############
		$apsw = Gtk2::ScrolledWindow->new(undef, undef);
			$apsw->set_shadow_type('etched-out');
		$apsw->set_policy('automatic', 'automatic');
		$apsw->set_size_request(800,300);
		$apsw->set_border_width(5);

		# AP Table

		# IMPORTANT: Must correspond to the number of cells
		$ap_tree_store = Gtk2::TreeStore->new(qw/Glib::String Glib::String Glib::String Glib::String Glib::String Glib::String Glib::String Glib::String Glib::String Glib::String Glib::String Glib::String/);

		#this will create a treeview, specify $tree_store as its model
		$ap_tree_view = Gtk2::TreeView->new($ap_tree_store);

		# Generate AP Information Columns
		my @ap_cols = qw/SSID BSSID Time Packets Plugin Event Timestamp Encryption Power Channel Latitude Longitude/;
		my $col_count = 0;
		foreach (@ap_cols) {
			my $label = $_;
			my $col = Gtk2::TreeViewColumn->new();
			$col->set_title("$label");
			
				my $col_renderer = Gtk2::CellRendererText->new;
				$col->pack_end($col_renderer, FALSE);
				$col->add_attribute($col_renderer, markup => $col_count);
				$col->set_sort_column_id($col_count);
				$ap_tree_view->append_column($col);
				$col_count++;
		}	

		 # make it searchable
   		$ap_tree_view->set_search_column(0);
	  
		# Allow drag and drop reordering of rows
        	$ap_tree_view->set_reorderable(TRUE);

		$apsw->add($ap_tree_view);

		# AP Information Tab
		my $ap_tab_hbox = Gtk2::HBox->new(FALSE,0);

			my $aplabel =Gtk2::Label->new("AP Information");
			$ap_tab_hbox->pack_start($aplabel,FALSE,FALSE,0);		

			my $apbutton = Gtk2::Button->new('');
			$apbutton->set_image(Gtk2::Image->new_from_stock('gtk-close','menu'));
			$apbutton->set_relief('none');
			$apbutton->signal_connect('clicked' => sub {
				$view_menu_ap->set_active(FALSE);
				$apsw->hide_all;
			});
			$ap_tab_hbox->pack_start($apbutton,FALSE,FALSE,0);
			$ap_tab_hbox->show_all();

		$nb->append_page($apsw, $ap_tab_hbox);

		############# PLUGIN INFORMATION TAB #############
		# TODO: add functionality to plugin tab
		$pluginsw = Gtk2::ScrolledWindow->new(undef, undef);
		$pluginsw->set_shadow_type('etched-out');
		$pluginsw->set_policy('automatic', 'automatic');
		$pluginsw->set_size_request(800,300);
		$pluginsw->set_border_width(5);

		# AP/Plugins Tree
		$tree_store = Gtk2::TreeStore->new(qw/Glib::String/);


		#this will create a treeview, specify $tree_store as its model
		$tree_view = Gtk2::TreeView->new($tree_store);

		
		#create a Gtk2::TreeViewColumn to add to $tree_view
		my $tree_column = Gtk2::TreeViewColumn->new();
		
		$tree_column->set_title ("Sort");
			
			#create a renderer that will be used to display info
			#in the model
			my $renderer = Gtk2::CellRendererText->new;

			#add this renderer to $tree_column. This works like a Gtk2::Hbox	
			$tree_column->pack_start ($renderer, FALSE);
		
			 # set the cell "text" attribute to column 0   
			 #- retrieve text from that column in treestore
			$tree_column->add_attribute($renderer, text => 0);
	
			#add $tree_column to the treeview
			$tree_view->append_column ($tree_column);
		
		 # make it searchable
   		$tree_view->set_search_column(0);
	
		# Allow sorting on the column
		$tree_column->set_sort_column_id(0);
   
		# Allow drag and drop reordering of rows
        	$tree_view->set_reorderable(TRUE);

		$pluginsw->add($tree_view);

		# Plugin Information Tab
		my $plugin_tab_hbox = Gtk2::HBox->new(FALSE,0);

			my $pluginlabel =Gtk2::Label->new("Plugin Information");
			$plugin_tab_hbox->pack_start($pluginlabel,FALSE,FALSE,0);		

			my $pluginbutton = Gtk2::Button->new('');
			$pluginbutton->set_image(Gtk2::Image->new_from_stock('gtk-close','menu'));
			$pluginbutton->set_relief('none');
			$pluginbutton->signal_connect('clicked' => sub {
				$pluginsw->hide_all;
				$view_menu_plugin->set_active(FALSE);
			});
			$plugin_tab_hbox->pack_start($pluginbutton,FALSE,FALSE,0);
			$plugin_tab_hbox->show_all();

		$nb->append_page($pluginsw, $plugin_tab_hbox);


	$vbox->pack_start($nb,TRUE,TRUE,0);

		# Output Frame
		$frame = Gtk2::Frame->new("Output");
		$frame->set_border_width(5);

		# Output Scrolled Window
		my $sw = Gtk2::ScrolledWindow->new (undef, undef);
		$sw->set_shadow_type ('etched-out');
		$sw->set_policy ('automatic', 'automatic');
		$sw->set_size_request (800,200);
		$sw->set_border_width(5);

			# Creates view window and sets properties
			my $tview = Gtk2::TextView->new();
			$tview->set_editable(FALSE);
			$tview->set_cursor_visible(FALSE);
			$tview->set_wrap_mode("word");

			# Set initial view window content
			my $content = "GUI interface for wicrawl, a modular and thorough wifi scanner\n" ;
			$buffer = $tview->get_buffer();

		 	$buffer->create_tag ("black", justification => "left");
		 	$buffer->create_tag ("orange", foreground => "orange");
		 	$buffer->create_tag ("red", foreground => "red");


			$buffer->set_text($content);

			# every  time we insert text, scroll to that mark
			my $end_mark = $buffer->create_mark('end', $buffer->get_end_iter, FALSE);

			$buffer->signal_connect (insert_text=>sub {
				$tview->scroll_to_mark ($end_mark, 0.0, TRUE, 0.0, 0.5);
			});

		$sw->add($tview);

		$frame->add($sw);
	


	$vbox->pack_start($frame,TRUE,TRUE,0);

	$vbox->show_all();
	
	# Return generated VBox
	return $vbox;
}
#######################################################################
# function start_button - takes care of start triggers
#	Arguments: None
#	Returns:None

sub start_button {
	if($t_start_button->get_label eq 'Start') {
				
				# scan through interfaces to find if they
        # were checked for scan
				my $flag = 0;
				foreach (values %interface) {
					$flag = $flag || $_;
				}

				# make sure at least one interface was selected
				if($flag) {
					$t_start_button->set_label('Stop');
					# Top Menu
					$wicrawl_menu_start->hide_all;
					$wicrawl_menu_stop->show_all;
					&wicrawl_exec();
				} else {
				lprint(2,0,"No Interfaces were selected, please select at least one interface for wicrawl to begin the scan.\n");

				}
			}
	elsif($t_start_button->get_label eq 'Stop') {
				lprint(0,1,"Stop was pressed\n");
				$t_start_button->set_label('Start');	
				# Top Menu
				$wicrawl_menu_start->show_all;
				$wicrawl_menu_stop->hide_all;
				Gtk2::Helper->remove_watch($helper_tag);

				lprint(0,3, "Killing child [$pid]\n");
				kill(2, $pid);
				my $kid=waitpid($pid, WNOHANG);
				if($kid <= 0) {
					waitpid($pid, 0);
				}
				lprint(0,3, "Child [$pid] dead\n");
				lprint(1,1, "Discovery and plugin-engine finished\n");

				close($fh);

				#change logo
				$image->set_from_file("$image_dir/Mrl.jpg");
	}

}


#######################################################################
#function wicrawl_exec
#	Arguments: None
#		Returns: None
####################
sub wicrawl_exec {

			my $interface = $monitor_interface;
			foreach my $key (sort keys %interface) {
				if($interface{$key}) {
					unless($key eq $monitor_interface) { $interface .= ",$key"; }
				}
			}

			$runtime = time;

			lprint(0,1,"Starting wi-crawl...\n");

			my $verbosity_pe = $preferences->verbosity_pluginengine;

			my @args=("$wicrawl", "-i", "$interface", "-f", "wicrawl_discovery-$runtime.xml", "-w", "-d", $outputdir, "-P wicrawl_plugins-output-$runtime.xml","-s $runtime","-v $verbosity_pe");

			# Check for SSID Filter
			if($entry->get_text) {
				$filter = $entry->get_text;
				push @args, "-F \"$filter\"";
			} else {
				$filter = "";	# resets filter
			}

			# Check for Profile
			if($default_profile) {
				push @args, "-p $default_profile";
	
				my $current_profile = &get_profile($default_profile);
				if($current_profile->killdisc eq "true") {
					push @args, "-k";
				}
			}


			lprint(1,3, "Wicrawl execution command line: @args\n");

			# Get output from wicrawl
			$fh = FileHandle->new;
			$pid=open($fh, "-|", "@args") or lprint(0,3,"\nCouldn't open wicrawl pipe\n");

			# set the process group id so we can kill all children
			setpgrp($pid, $pid);

			$helper_tag = Gtk2::Helper->add_watch(fileno $fh, 'in', sub {
					&watch_callback($fh);
			});

			
}

# Utility function for wicrawl_exec function
sub watch_callback {
	my ($fh) = @_;
	my $line;
	# read 1000 characters of the buffer

	&find_aps();
	$fh->sysread($line, 500);

	if($fh->error) {
		lprint(2,0,"FileHandler had problems");
	}

	if($line) {
		lprint(0,2,"$line");
	}

	else {
		# the connected pipe was closed
		lprint(0,1,"Wicrawl is finished\n");
		$wicrawl_menu_start->show_all;
		$wicrawl_menu_stop->hide_all;
		$t_start_button->set_label('Start');	
		Gtk2::Helper->remove_watch($helper_tag) or lprint(2,0,"\nCouldn't Remove Watch Callback\n");

		lprint(0,3, "Killing child [$pid]\n");
		kill(2, $pid);
		my $kid=waitpid($pid, WNOHANG);
		if($kid <= 0) {
			waitpid($pid, 0);
		}
		lprint(0,3, "Child [$pid] dead\n");
		lprint(1,1, "Discovery and plugin-engine finished\n");

		close($fh);
	}

	# Return TRUE so we can loop again
	return TRUE;
}
#######################################################################
#function find_aps - Constantly checks whether new APs were discovered 
#	Arguments: none
#	Returns: TRUE
####################
sub find_aps {	
	# sets fixed xml path to the wicrawl output
	$apcoredb = "$outputdir/wicrawl_discovery-$runtime.xml";
	&show_data();
	#&get_ap();

	#TODO: temp solution
	$plugincoredb = "$outputdir/wicrawl_plugins-output-$runtime.xml";
	&get_plugins();

	# Always return TRUE to continue the loop
	return TRUE;
}

#######################################################################
#function show-data - gets AP and displays them in AP frame
#	Arguments: Simple List
# 		Returns: None
####################
sub show_data {

	# adding rows with APs
	my @APS;
	@APS = &get_ap;	

	my $wepcount = 0;
	my $packets = 0;
	my $totalap = 0;

	my $haveinternet = 0;
	my $newap = 0;
	my $ip = 0;
	my $associated = 0;

	# clear to display fresh data
	$ap_tree_store->clear;

	foreach (@APS) {

	#collect statistical information
	$totalap++;
	$packets += $_->{PACKETS};
	if($_->{ENCRYPTION} eq "WEP") {$wepcount++}
	if($_->{EVENT} eq "have-internet") {$haveinternet++}
	if($_->{EVENT} eq "new-ap") {$newap++}
	if($_->{EVENT} eq "associated") {$associated++}
	if($_->{EVENT} eq "have-ip") {$ip++}


       	 my $ap= $ap_tree_store->append(undef);	
		#the iter is a pointer in the treestore. We
		#use to add data.

		#get correct color for the row
		my $color = "black";
		my $event = $_->{EVENT};
		if ($event eq "new-ap") {
			$color = "red";
		}
		elsif ($event eq "associated") {
			$color = "orange";
		}
		elsif ($event eq "have-internet") {
			$color = "darkgreen";
		}
		else {
			$color = "black";
		}

		#fix timestamp
		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($_->{TIMESTAMP});
		$year += 1900;
		my $timestamp = "$mon-$mday-$year $hour:$min:$sec";

		my $color_image = "$image_dir/mrl-$color.jpg";
		if($color ne "black") {

			$image->set_from_file($color_image);
	

			$ap_tree_store->set($ap,0,"<span foreground='$color'>$_->{SSID}</span>");
			$ap_tree_store->set ($ap,1 => "<span foreground='$color'>$_->{BSSID}</span>");
			$ap_tree_store->set ($ap,2 => "<span foreground='$color'>$_->{TIME}</span>");
			$ap_tree_store->set ($ap,3 => "<span foreground='$color'>$_->{PACKETS}</span>");
			$ap_tree_store->set ($ap,4 => "<span foreground='$color'>$_->{PLUGIN}</span>");
			$ap_tree_store->set ($ap,5 => "<span foreground='$color'>$_->{EVENT}</span>");
			$ap_tree_store->set ($ap,6 => "<span foreground='$color'>$timestamp</span>");
			$ap_tree_store->set ($ap,7 => "<span foreground='$color'>$_->{ENCRYPTION}</span>");
			$ap_tree_store->set ($ap,8 => "<span foreground='$color'>$_->{POWER}</span>");
			$ap_tree_store->set ($ap,9 => "<span foreground='$color'>$_->{CHANNEL}</span>");
			$ap_tree_store->set ($ap,10 => "<span foreground='$color'>$_->{LATITUDE}</span>");
			$ap_tree_store->set ($ap,11 => "<span foreground='$color'>$_->{LONGITUDE}</span>");
		} else {
			# this is to make themes work
			$ap_tree_store->set($ap,0,"$_->{SSID}");
			$ap_tree_store->set ($ap,1 => "$_->{BSSID}");
			$ap_tree_store->set ($ap,2 => "$_->{TIME}");
			$ap_tree_store->set ($ap,3 => "$_->{PACKETS}");
			$ap_tree_store->set ($ap,4 => "$_->{PLUGIN}");
			$ap_tree_store->set ($ap,5 => "$_->{EVENT}");
			$ap_tree_store->set ($ap,6 => "$timestamp");
			$ap_tree_store->set ($ap,7 => "$_->{ENCRYPTION}");
			$ap_tree_store->set ($ap,8 => "$_->{POWER}");
			$ap_tree_store->set ($ap,9 => "$_->{CHANNEL}");
			$ap_tree_store->set ($ap,10 => "$_->{LATITUDE}");
			$ap_tree_store->set ($ap,11 => "$_->{LONGITUDE}");
		}
	}

	if($totalap) {

	my $ratio = int($wepcount*100/$totalap);

	my $msg = "<span size='x-large'>Total APs: $totalap\t";
	$msg .= "Encrypted: $wepcount\t";
	$msg .= "Ratio: $ratio%\t";
	$msg .= "Packets: $packets</span>\n";
	$infobar_buffer->set_markup($msg);

	# colorbar
	my $width = 153;
	my $colorbar_newap = int($newap/$totalap*$width);
	my $colorbar_associated = int($associated/$totalap*$width);
	my $colorbar_ip = int($ip/$totalap*$width);
	my $colorbar_internet = int($haveinternet/$totalap*$width);

	# now let's generate a bar
	my $colorbar_markup = "<span background = 'black' foreground='white'>";
	my $unknown_state = $width - $colorbar_newap - $colorbar_associated - $colorbar_ip - $colorbar_internet;
	my $unknown_number = $totalap - $newap - $associated - $ip - $haveinternet;
	for(my $i=0; $i < $unknown_state; $i++) { 
		if($i == int($unknown_state/2)) {
			if($unknown_number) {
				$colorbar_markup .= "$unknown_number"; 
			}
		}
		else {$colorbar_markup .= " "; }
	}
	$colorbar_markup .= "</span>";

	#newap info
	$colorbar_markup .= "<span background = 'red' foreground = 'white'>";
	for(my $i = 0; $i < $colorbar_newap; $i++) { 
		if($i == int($colorbar_newap/2)) {$colorbar_markup .= "$newap"; }
		else {$colorbar_markup .= " "; } 
	}
	$colorbar_markup .= "</span>";
	#associated info
	$colorbar_markup .= "<span background = 'orange' foreground='white'>";
	for(my $i = 0; $i < $colorbar_associated; $i++) { 
		if($i == int($colorbar_associated/2)) {$colorbar_markup .= "$associated"; }
		else {$colorbar_markup .= " "; } 
	}
	$colorbar_markup .= "</span>";
	#have-ip info
	$colorbar_markup .= "<span background = 'blue' foreground='white'>";
	for(my $i = 0; $i < $colorbar_ip; $i++) { 
		if($i == int($colorbar_ip/2)) {$colorbar_markup .= "$ip"; }
		else {$colorbar_markup .= " "; } 
	}
	$colorbar_markup .= "</span>";
	#have-internet info
	$colorbar_markup .= "<span background = 'darkgreen' foreground='white'>";
	for(my $i = 0; $i < $colorbar_internet; $i++) { 
		if($i == int($colorbar_internet/2)) {$colorbar_markup .= "$haveinternet"; }
		else {$colorbar_markup .= " "; } 
	}
	$colorbar_markup .= "</span>";


	$colorbar->set_markup($colorbar_markup);
	
	} else {
		$infobar_buffer->set_markup("Scanning...\n");
		my $color_image = "$image_dir/Mrl.jpg";
		$image->set_from_file($color_image);
	}
}

#######################################################################
# function get_ap - Get the next AP to use
#		Arguments: none
#		Returns @ap
#
sub get_ap() {
	my(@wireless, @APS);
	my $XML; 
	my $count=0;

	my $size=(stat("$apcoredb"))[7];

	# We only want to search through the xml file if it exists
	# Otherwise it will create an empty entry
	if ((defined($size)) && ($size >= 122)) {

		$XML = XML::Smart->new($apcoredb);
		if($cutroot) {
			$XML = $XML->cut_root;
		}
		@wireless = @{$XML->{"wireless-network"}};
		#lprint(0, 2, "Scanning input XML file\n");
			foreach(@wireless) {
	
			# Don't want to get APs with no ssid for now
			next if((!defined($_->{SSID})) || ($_->{SSID} eq ""));
	
			my $ap=AccessPoint->new();
			$ap->ssid            ($_->{SSID});
			$ap->bssid          ($_->{BSSID}); 
			$ap->time                     (0); # TODO get from meta-tags
			$ap->packets                  (0); # TODO get from meta-tags
			$ap->plugin                   ($_->{plugin});
			$ap->event                    ($_->{event}); 
			$ap->timestamp                ($_->{timestamp}); 
			$ap->encryption($_->{encryption}); 
			# JRS
			$ap->power                    ($_->{power});
			$ap->channel      ($_->{channel});
			$ap->longitude ($_->{longitude});
			$ap->latitude($_->{latitude});
	
			# This gets 99.85 percent of the AP's that i've seen
			next if ($ap->ssid =~ /[^\w\s,-_\.\^!#]/);

			if((defined($filter)) && ($filter ne "") && ($ap->ssid !~ /$filter/)) {
				lprint(1, 3, "This AP [" . $ap->ssid . "] doesn't match your filter of [$filter]\n");
				next;
			}
	
			#lprint(0, 3, "Adding AP ssid [" . $ap->ssid . "]\n");
			$APS[$count]=$ap;		
			$count++;
		}
		if($count==0) {
			lprint(1, 1, "Couldn't find any APs, trying again\n");
		}
	} else {
		#print "Couldn't open $apcoredb";
	}
	
	return @APS;
}


#######################################################################
# function get_plugin - reads plugin information from xml file
#	Arguments: none
#		Returns: none

sub get_plugins() {

	my(@accesspoint, @PLUGINS);
	my $XML; 
	my $count=0;

	$XML = XML::Smart->new($plugincoredb);

	my $size=(stat("$plugincoredb"))[7];

	# We only want to search through the xml file if it exists
	# Otherwise it will create an empty entry
	if ((defined($size)) && ($size >= 122)) {

		if($cutroot) {
			$XML = $XML->cut_root;
		}

		my @expanded;

		my $start_iter = $tree_store->get_iter_first;
		while($start_iter) {
			my $path = $tree_store->get_string_from_iter($start_iter);
			
			if($tree_view->row_expanded(Gtk2::TreePath->new_from_string($path))) { 
				#print "pushing $path\n";
				push @expanded, $path; 
			
				# Do we have runlevels?
				if($tree_store->iter_has_child($start_iter)) {
					my $iter_runlevels = $tree_store->iter_n_children($start_iter);
					while ($iter_runlevels) {
						$iter_runlevels--;
						my $runpath = "$path:$iter_runlevels";
						if($tree_view->row_expanded(Gtk2::TreePath->new_from_string($runpath))) {
							#print "pushing $runpath\n";
							push @expanded, $runpath;

							# And at last let's check which plugins are expanded
							my $iter_plugin = $tree_store->get_iter_from_string($runpath);
							if($tree_store->iter_has_child($iter_plugin)) {
								my $iter_plugin_count = $tree_store->iter_n_children($iter_plugin);
								while($iter_plugin_count) {
									$iter_plugin_count--;
									my $pluginpath = "$runpath:$iter_plugin_count";
									if($tree_view->row_expanded(Gtk2::TreePath->new_from_string($pluginpath))) {
										#print "pushing $pluginpath\n";
										push @expanded, $pluginpath;
									}
								}
							}

						}
					}
				}
			}

			$start_iter = $tree_store->iter_next($start_iter);
		}


		# clear slist to display fresh data
		$tree_store->clear;

		@accesspoint = @{$XML->{"accesspoint"}};
		#lprint(0, 2, "Scanning input XML file\n");
		print @accesspoint;

		foreach(@accesspoint) {

			#if((defined($filter)) && ($filter ne "") && ($_->ssid !~ /$filter/)) {
			#	lprint(0, 2, "This AP [" . $_->ssid . "] doesn't match your filter of [$filter]\n");
			#	next;
			#}

			#the iter is a pointer in the treestore. We
			#use to add data.
        	        my $ap= $tree_store->append(undef);
			$tree_store->set ($ap,0 => "$_->{ssid} ($_->{bssid})");

			my @plugin = @{$_->{"plugin"}};
	
			my $plugin; # used for individual plugins
			my $current_run =-1;
			my $run_tree;
	
			foreach $plugin (@plugin) {
				my $plugin_run = $plugin->{run};
				my $plugin_name = $plugin->{name};
 				my $output = decode_base64($plugin->{output});

				if($current_run != $plugin_run) {
					$run_tree = $tree_store->append($ap);
					$tree_store->set($run_tree,0 => "Run $plugin_run");
					$current_run = $plugin_run;
				}

				my $plugin = $tree_store->append($run_tree);
				$tree_store->set ($plugin,0 => "$plugin_name");

				my $plugin_output = $tree_store->append($plugin);
				$tree_store->set($plugin_output,0 => "$output");

				#print "$output\n";
			}
	
			#$PLUGINS[$count]=$ap;		
			$count++;

		}

		#restore expanded rows
		foreach(@expanded) {
			#print "Expanding $_\n";
			$tree_view->expand_to_path(Gtk2::TreePath->new_from_string("$_"));
		}


		if($count==0) {
			lprint(1, 1, "Couldn't find any APs, trying again\n");
		}
	} else {
		#print "Couldn't open $plugincoredb";
	}

	#return @PLUGINS;
	
}

#######################################################################
# function lprint - log print function
# 	Arugments: type of buffer, message (int), loglevel (int), string of $msg
#		Returns: 0
#		Notes:  
#			Loglevels are:
#				0 = Errors and fatal  (Always shown, -q for quiet)
#				1 = Default logging   (default log level)
#				2 = More info  				(-v)
#				3 = All info          (-vv)
#			Message Types are:
#				0 = Info (black)
#				1 = Notice (orange)
#				2 = Error (red)
####################
sub lprint {
	my $type=shift(@_);
	my $loglevel=shift(@_);
	my $msg=shift(@_);
	
 	my $color="black";

	# set the prefix character: '!' is err, '*' is notice
	if ($type==1) {
		$color="orange";
	}	elsif ($type==2) {
		$color="red";
	}

	my $verbosity = $preferences->verbosity_ui;

	# print if loglevel is high enough
	if($loglevel <= $verbosity) {
		#print $msg; # prints output to the console
		$buffer->insert_with_tags_by_name ($buffer->get_end_iter, $msg, $color);
	}

	# log everything
	# open(LOG, ">>$logfile") || die "  [!!!] Can't open logfile $logfile\n";
	# close(LOG) || die "  [!!!] Can't close logfile $logfile\n";
	
	#$buffer->insert ($buffer->get_end_iter, $msg);
	
	return 0;
}

#######################################################################
#function get_interfaces - Checks the available interfaces on the system and adds the appropriate checkboxes
#	Arguments: none
#	Returns: none
###################
sub get_interfaces {
	#print "Finding Available Interfaces\n";
	my @args=("$basedir/discovery/apcore", "-l");

	foreach( `@args`) {
		my($id, $interface_name) = /(\S+) (\S+)/;
		# initialize an interface hash and preset key values
    # with zero's so that interfaces were disabled by default
		$interface{$interface_name} = 0;
	}
}
#######################################################################
#function find_plugins - finds available plugins
#	Arguments: none
#	Returns: none
###################
sub find_plugins {
	#print "Getting Plugins\n";
	
	my $plugins_dir = "$basedir/plugins";
	
	opendir SOMEDIR, $plugins_dir or lprint(1,0,"Could not open $plugins_dir");
	while (my $plugin_name = readdir SOMEDIR) {
		next if $plugin_name =~ /^\./;	# skip over dot files
		next if $plugin_name =~/CVS/; # CVS workaround
		my $fullpath = "$plugins_dir/$plugin_name";
		#print $fullpath;
		if(-d $fullpath) {
			#$profile =~ s/\.conf//;
			push @plugins, $plugin_name;
			#print "Found Plugin $plugin_name\n";
		}
	}
}

#######################################################################
#function find_themes - finds available plugins
#	Arguments: none
#	Returns: none
###################
sub find_themes {
	#print "Getting Themes\n";
	
	my $themes_dir = "$basedir/ui/themes";

	# push default theme
	push @themes, "default";
	
	opendir THEMEDIR, $themes_dir or lprint(2,0,"Could not open $themes_dir");
	while (my $theme_name = readdir THEMEDIR) {
		next if $theme_name =~ /^\./;	# skip over dot files
		next if $theme_name =~/CVS/; # CVS workaround
		my $fullpath = "$themes_dir/$theme_name";
		#print $fullpath;
		if(-d $fullpath) {
			push @themes, $theme_name;
		}
	}
}

#######################################################################
#function get_profiles - Checks available profiles
#	Arguments: none
#	Returns: none
###################
sub get_profiles {
	#print "Getting Profiles\n";
	
	my $profiles_dir = "$basedir/profiles";
	
	opendir SOMEDIR, $profiles_dir or lprint(2,0,"Could not open $profiles_dir");
	while (my $profile = readdir SOMEDIR) {
		next if $profile =~ /^\./;	# skip over dot files
		if($profile =~ /.*\.conf/) {
			$profile =~ s/\.conf//;
			push @profiles, $profile;
			#print "Found Profile $profile";
		}
	}
}

#######################################################################
# function get_preferences - returns preferences
#	Returns: theme name
sub get_preferences() {

	use vars qw($theme $verbosity_pluginengine $verbosity_ui);

	my $theme_conf = "$confdir/wicrawl-gtk.conf";
	if(-r $theme_conf) {
		unless (my $return = do $theme_conf) {
			lprint(2,0, "Couldn't parse $theme_conf: $@") if $@;
			lprint(2,0, "Couldn't run $theme_conf: $!") unless defined $return;
			lprint(2,0, "Couldn't run $theme_conf") unless $return
		}
	} else {
		lprint(2,0, "Can't find $theme_conf. Exiting...\n");
		exit 1;
	}

	do $theme_conf;
	my $preferences = Preferences->new();
	$preferences->theme($theme);
	$preferences->verbosity_pluginengine($verbosity_pluginengine);
	$preferences->verbosity_ui($verbosity_ui);

	return $preferences;

}


#######################################################################
# function get_profile - loads the current profile information
# 	Arugments: profile name
#		Returns: profile object
####################
sub get_profile() {
	my $profile_to_load = shift @_;
	use vars qw($enabled_plugins $runlengths $card_scheduling $killdisc);

	# TODO Load the specified profile rather than default
	my $profile_conf="$profiledir/$profile_to_load$profileext";
	lprint(0, 1, "Loading profile... [$profile_conf]\n");

	if(-r $profile_conf) {
		unless (my $return = do $profile_conf) {
			die "  [!!] Couldn't parse $profile_conf: $@" if $@;
			die "  [!!] Couldn't run $profile_conf: $!"    unless defined $return;
			die "  [!!] Couldn't run $profile_conf"       unless $return;
		}
	} else {
		lprint(2, 0, "Can't find the given profile in \"$profile_conf\".  Exiting...\n");
		exit 1;
	}

	do $profile_conf;
	my $profile=Profile->new;

	# Get the list of plugins to run
	$profile->plugins($enabled_plugins);

	# Verify that the runlengths are valid
	my $count=0;
	my @runlengths=split(/\s/, $runlengths);
	foreach(@runlengths) {
		if(! /(short|medium|long)/) {
			# Pull the runlength out if it doesn't match. 
			lprint (2, 0, "Profile runlegth \"$_\" is not valid, removing...\n");
			$runlengths=~s/\b$_\b//;
		}
		$count++;
	}

	$profile->runlengths($runlengths);
	lprint(0, 1, "Using runlengths: [" . $profile->runlengths . "]\n");

	# Get the card scheduler
	if($card_scheduling !~ /(first|active|signal|all)/) {
		my $msg="Profile $default_profile does not have a valid scheduling type\n";
		$msg .= "     using default of $default_scheduling instead\n";
		lprint(2, 1, $msg);

		# TODO change to specified profile rather than the default
		$profile->scheduling($default_scheduling);
	} else {
		$profile->scheduling($card_scheduling);
	}

	# Kill discovery between runs
	$profile->killdisc($killdisc);
	

	lprint(0, 3, "Using scheduling type [" . $profile->scheduling . "]\n");
	lprint(0, 2, "Done loading profile.\n");
	return $profile;
}			

#######################################################################
# function profile_tab - takes care of generating a profile tab specific to selected profile
#

sub profile_tab {
		my $current_profile;
		if($default_profile ne "New") {$current_profile = &get_profile($default_profile);}
		else {
			$current_profile = Profile->new;
			$current_profile->scheduling("");
			$current_profile->plugins("");
			$current_profile->runlengths("");	
			$current_profile->killdisc("");
		}
		my $profile_tab = Gtk2::Frame->new();

		# Profile Configuration Selection
			my $profile_hbox = Gtk2::HBox->new(FALSE,0);

			# FIRST COL
			my $first_col = Gtk2::VBox->new(FALSE,0);

			# Profile Name

			my $profile_name_frame = Gtk2::Frame->new("Name");
			$profile_name_frame->set_shadow_type('none');
			my $profile_name_box = Gtk2::VBox->new(FALSE,0);

				my $name_entry = Gtk2::Entry->new();
				$name_entry->set_text($default_profile);
				$profile_name_box->pack_start($name_entry,FALSE,FALSE,0);

			$profile_name_frame->add($profile_name_box);
			$first_col->pack_start($profile_name_frame,FALSE,FALSE,5);
			
			# Profile Scheduling
			my $profile_scheduling_frame = Gtk2::Frame->new("Scheduling");
			$profile_scheduling_frame->set_shadow_type('none');
			my $profile_scheduling_box = Gtk2::VBox->new(FALSE,0);

				my $profile_scheduling_group;
				foreach (@card_scheduling) {
					my $label = $_;
					my $scheduling = $_;
					$scheduling = Gtk2::RadioButton->new($profile_scheduling_group, "$label");
					$scheduling->signal_connect('toggled' => sub {
							$current_profile->scheduling($label);
						});
					if ($current_profile->scheduling eq "$label") {
						$scheduling->set_active(TRUE);
					} else {
						$scheduling->set_active(FALSE);
					}
					$profile_scheduling_group = $scheduling->get_group;	
					$profile_scheduling_box->pack_start($scheduling,FALSE,FALSE,0);
				}		

			$profile_scheduling_frame->add($profile_scheduling_box);
			$first_col->pack_start($profile_scheduling_frame,FALSE,FALSE,5);

			# Profile Runlength
			my $profile_runlength_frame=Gtk2::Frame->new("Runlengths");
			$profile_runlength_frame->set_shadow_type('none');
			my $profile_runlength_box = Gtk2::VBox->new(FALSE,0);

			my %active_runlengths;
			
				foreach(@runlengths) {
					my $runlength = $_;
					my $label = $_;

					$runlength = Gtk2::CheckButton->new("$label");
					$runlength->signal_connect('toggled' => sub {
						my $label = $runlength->get_label;
						if($runlength->get_active) {
							$active_runlengths{$label} = $label;
						}
						else {
							delete($active_runlengths{$label});
						}
						});
					if($current_profile->runlengths =~ m/$label/) {
						$runlength->set_active(TRUE);
					}
					$profile_runlength_box->pack_start($runlength,FALSE,FALSE,0);
				}
	
			$profile_runlength_frame->add($profile_runlength_box);
			$first_col->pack_start($profile_runlength_frame,FALSE,FALSE,5);	

			# Profile Kill Between Runs
			my $profile_killdisc_frame = Gtk2::Frame->new("Discovery Engine");
			$profile_killdisc_frame->set_shadow_type('none');
			my $profile_killdisc_box = Gtk2::VBox->new(FALSE,0);

				my $killdisc_button = Gtk2::CheckButton->new("Kill between runs");
				if(defined $current_profile->killdisc && $current_profile->killdisc eq "true") {$killdisc_button->set_active(TRUE);}
				$profile_killdisc_box->pack_start($killdisc_button,FALSE,FALSE,0);

			$profile_killdisc_frame->add($profile_killdisc_box);
			$first_col->pack_start($profile_killdisc_frame,FALSE,FALSE,0);

			$profile_hbox->pack_start($first_col,FALSE,FALSE,0);

			# Profile Plugins
			my $profile_plugins_frame = Gtk2::Frame->new("Plugins");
			$profile_plugins_frame->set_shadow_type('none');
			my $profile_plugins_box = Gtk2::VBox->new(FALSE,0);

			my %active_plugins;

				foreach(@plugins) {
					my $plugin = $_;
					my $label = $_;
		
					$plugin = Gtk2::CheckButton->new("$label");
					$plugin->signal_connect('toggled' => sub {
						my $label = $plugin->get_label;
						if($plugin->get_active) {
							$active_plugins{$label} = $label;
						}
						else {
							delete($active_plugins{$label});							
						}
					});
					if($current_profile->plugins =~ m/$label/) {
						$plugin->set_active(TRUE);
					}
					$profile_plugins_box->pack_start($plugin,FALSE,FALSE,0);
	
				}

			$profile_plugins_frame->add($profile_plugins_box);
			$profile_hbox->pack_start($profile_plugins_frame,FALSE,FALSE,5);	


			# Save Button
			my $profile_buttons_frame = Gtk2::Frame->new;
			$profile_buttons_frame->set_shadow_type('none');
			my $profile_buttons_box = Gtk2::VBox->new(FALSE,0);

				my $save_button = Gtk2::Button->new_from_stock("gtk-save");
				$save_button->signal_connect('clicked' => sub {
					# generate updated profile
					print "Save Button Pressed\n";
					my $temp = "";
					# get selected plugins
					foreach (keys %active_plugins) {
						if($temp) {$temp .= " $_";}
						else {$temp .= "$_";}
					}
					$current_profile->plugins($temp);
					$temp = "";

					# get selected runlevels
					foreach (keys %active_runlengths) {
						if($temp) {$temp .= " $_";}
						else {$temp .= "$_";}
					}
					$current_profile->runlengths($temp);

					
					# get new/old name
					if($name_entry->get_text) {
						$default_profile = $name_entry->get_text;
					}

					# get discovery engine selection
					if($killdisc_button->get_active) {
						$current_profile->killdisc("true");
					} else {
						$current_profile->killdisc("false");
					}
					

					&save_profile($current_profile, $default_profile);
					
				});
				$profile_buttons_box->pack_start($save_button, FALSE, FALSE, 5);

			$profile_buttons_frame->add($profile_buttons_box);
			$profile_hbox->pack_start($profile_buttons_frame, FALSE,FALSE,5);
					
		$profile_tab->add($profile_hbox);

		# top menu tabs
	
		my $tabs_profile = Gtk2::MenuItem->new_with_mnemonic("Profile: $default_profile");
		$tabs_profile->signal_connect('activate' => sub {
			$nb->set_current_page($nb->page_num($profile_tab));
					});
		$tabs_menu->append($tabs_profile);
		$tabs_menu->show_all;

		# Profile Information Tab
		my $profile_tab_hbox = Gtk2::HBox->new(FALSE,0);

			my $profilelabel =Gtk2::Label->new("Profile: $default_profile");
			$profile_tab_hbox->pack_start($profilelabel,FALSE,FALSE,0);		

			my $profilebutton = Gtk2::Button->new('');
			$profilebutton->set_image(Gtk2::Image->new_from_stock('gtk-close','menu'));
			$profilebutton->set_relief('none');
			$profilebutton->signal_connect('clicked' => sub {
				$nb->remove($profile_tab);
				$tabs_menu->remove($tabs_profile);
			});
			$profile_tab_hbox->pack_start($profilebutton,FALSE,FALSE,0);
			$profile_tab_hbox->show_all();

		$nb->append_page($profile_tab, $profile_tab_hbox);
		$profile_tab->show_all();
		$nb->set_current_page($nb->page_num($profile_tab));
}

#######################################################################
# function save_profile - saves profile to file
#	Arguments: Profile, Profile_File_Name

sub save_profile {
	print("Saving profile...\n");
	my $profile=shift(@_);
	my $profile_name =shift(@_);

	my $scheduling = $profile->scheduling;
	my $plugins = $profile->plugins;
	my $runlengths = $profile->runlengths;
	my $killdisc = $profile->killdisc;

	my $profile_path = "$basedir/profiles/$profile_name.conf";

	#print "My path is: $profile_path";

	if(-e "$profile_path") {
		open(DAT, $profile_path) or lprint(2,0, "Couldn't open profile: $profile_name");
		my @raw_data=<DAT>;
		close(DAT);

		#now let's add update information to the file
		foreach (@raw_data) {
			if(/\$card_scheduling/) {$_="\$card_scheduling=\"$scheduling\";"; }
			if(/\$enabled_plugins/) {$_="\$enabled_plugins=\"$plugins\";"; }
			if(/\$runlengths/) {$_="\$runlengths=\"$runlengths\";"; }
			if(/\$killdisc/) {$_="\$killdisc=\"$killdisc\";"; }
		}

		#print @raw_data;

		open(DAT, ">$profile_path") || lprint(2,0, "Couldn't save profile: $profile_name");
		print DAT @raw_data;
		close(DAT);
	}
	else {
		my $raw_data = "\#This profile was automatically generated by Wicrawl\n";
		      $raw_data .= "\# Card scheduling types:\n";
		      $raw_data .= "\#	first: Get the first AP available (Generally use this for \"mobile\")\n";
		      $raw_data .= "\#	active: Use the most active AP (in terms of traffic)\n";
		      $raw_data .= "\#	signal: Use the AP with the best signal\n";
		      $raw_data .= "\#	all:	   Try to get all access points\n";
		      $raw_data .= "\$card_scheduling=\"$scheduling\";\n";
		      $raw_data .= "\# space separated list of enabled plugins\n";
		      $raw_data .= "\$enabled_plugins=\"$plugins\";\n";
		      $raw_data .= "\# space separated list of runlevels to run for this profile\n";
		      $raw_data .= "\$runlengths=\"$runlengths\";\n";
		      $raw_data .= "\# kill discovey engine between runs (true or false)\n";
		      $raw_data .= "\$killdisc=\"$killdisc\";\n";

		open(DAT, ">>$profile_path") || lprint(2,0, "Couldn't save profile: $profile_name");
		print DAT $raw_data;
		close(DAT);

	}

	# open or create profile for writing

}


#######################################################################
# function read_plugins - Get the list of plugins for the current profile
# 	Arugments: none
#		Returns @array of plugins
#   TODO: use normal key=value pairs instead of perl style $key="value";
####################
sub get_plugin() {

	#$current_plugin = &get_plugin;
	
	my $plugin;
	my ($plugin_config, $return);

	# These are what we get from the plugin config file
	use vars qw($name $bin $version $monitor $runlength $offline $runlevel $event $timeout);

		$plugin_config="$plugindir/$default_plugin/$pluginext";
		if(-r $plugin_config) {
			unless ($return = do $plugin_config) {
				warn "  [!] Couldn't parse $plugin_config: $@" if $@;
				warn "  [!] Couldn't run $plugin_config: $!"   unless defined $return;
				warn "  [!] Couldn't run $plugin_config"       unless $return;
				next;
			}

			$plugin=Plugin->new();

			$plugin->populate($name, $bin, $version, $monitor, $runlength, $offline, $runlevel, $event, $plugin, $timeout);

			lprint(1, 2, "Added Plugin [$name] to active plugins\n");
			lprint(0, 3, "\tPlugin Version is     [$version]\n");
			lprint(0, 3, "\tEvent level is:       [$event]\n");
			lprint(0, 3, "\tRun length is:        [$runlength]\n");
			lprint(0, 3, "\tRun level is:         [$runlevel]\n");
			lprint(0, 3, "\tPlugin executable is  [$bin]\n");
		} else {
			lprint(2, 1, "Can't find the configured plugin\n\t(Trying $plugin_config)\n");
		}

	lprint(0, 2, "Done Loading plugins...\n");
	return $plugin;
}

#######################################################################
# function plugin_tab - create plugin tabs
#

sub plugin_tab {
		$current_plugin = &get_plugin;

		my $plugin_tab = Gtk2::Frame->new();

		# plugin Configuration Selection
			my $plugin_box = Gtk2::VBox->new(FALSE,0);
			
			# Monitor Mode
			my $plugin_monitor_frame = Gtk2::Frame->new("Monitor Mode");
			$plugin_monitor_frame->set_shadow_type('none');
			my $plugin_monitor_box = Gtk2::HBox->new(FALSE,0);

				my $plugin_monitor_group;

				# Yes Radio Button
				my $monitor_yes = Gtk2::RadioButton->new(undef, "yes");					
				$monitor_yes->signal_connect('toggled' => sub {
							$current_plugin->monitor("yes");
						});
				if ($current_plugin->monitor eq "yes") {
						$monitor_yes->set_active(TRUE);
					} else {
						$monitor_yes->set_active(FALSE);
					}
				$plugin_monitor_group = $monitor_yes->get_group;	
				$plugin_monitor_box->pack_start($monitor_yes,FALSE,FALSE,0);

				# No Radio Button
				my $monitor_no = Gtk2::RadioButton->new($plugin_monitor_group, "no");				
				$monitor_no->signal_connect('toggled' => sub {
							$current_plugin->monitor("no");
						});
				if ($current_plugin->monitor eq "no") {
						$monitor_no->set_active(TRUE);
					} else {
						$monitor_no->set_active(FALSE);
					}
				$plugin_monitor_group = $monitor_no->get_group;	
				$plugin_monitor_box->pack_start($monitor_no,FALSE,FALSE,0);
						

			$plugin_monitor_frame->add($plugin_monitor_box);
			$plugin_box->pack_start($plugin_monitor_frame,FALSE,FALSE,5);	


			# Offline Mode
			my $plugin_offline_frame = Gtk2::Frame->new("Offline Mode");
			$plugin_offline_frame->set_shadow_type('none');
			my $plugin_offline_box = Gtk2::HBox->new(FALSE,0);

				my $plugin_offline_group;

				# Yes Radio Button
				my $offline_yes = Gtk2::RadioButton->new(undef, "yes");				
				$offline_yes->signal_connect('toggled' => sub {
							$current_plugin->offline("yes");
						});
				if ($current_plugin->offline eq "yes") {
						$offline_yes->set_active(TRUE);
					} else {
						$offline_yes->set_active(FALSE);
					}
				$plugin_offline_group = $offline_yes->get_group;	
				$plugin_offline_box->pack_start($offline_yes,FALSE,FALSE,0);

				# No Radio Button
				my $offline_no = Gtk2::RadioButton->new($plugin_offline_group, "no");			
				$offline_no->signal_connect('toggled' => sub {
							$current_plugin->offline("no");
						});
				if ($current_plugin->offline eq "no") {
						$offline_no->set_active(TRUE);
					} else {
						$offline_no->set_active(FALSE);
					}
				$plugin_offline_group = $offline_no->get_group;	
				$plugin_offline_box->pack_start($offline_no,FALSE,FALSE,0);
						

			$plugin_offline_frame->add($plugin_offline_box);
			$plugin_box->pack_start($plugin_offline_frame,FALSE,FALSE,5);

			# Runlevel Mode
			my $plugin_runlevel_frame = Gtk2::Frame->new("Runlevel 0-99");
			$plugin_runlevel_frame->set_shadow_type('none');
			my $plugin_runlevel_box = Gtk2::VBox->new(FALSE,0);
				my $runlevel_entry = Gtk2::Entry->new_with_max_length(3);
				$runlevel_entry->set_text($current_plugin->runlevel);
				$plugin_runlevel_box->pack_start($runlevel_entry,FALSE,FALSE,0);			
			$plugin_runlevel_frame->add($plugin_runlevel_box);
			$plugin_box->pack_start($plugin_runlevel_frame,FALSE,FALSE,5);


			# Event
			my $plugin_event_frame = Gtk2::Frame->new("Event");
			$plugin_event_frame->set_shadow_type('none');
			my $plugin_event_box = Gtk2::HBox->new(FALSE,0);

				my $plugin_event_group;
				foreach (@events) {
					my $label = $_;
					my $event = $_;
					$event = Gtk2::RadioButton->new($plugin_event_group, "$label");			
					$event->signal_connect('toggled' => sub {
							my $label = $event->get_label;
							$current_plugin->event("$label");
						});
					if ($current_plugin->event eq "$label") {
						$event->set_active(TRUE);
					} else {
						$event->set_active(FALSE);
					}
					$plugin_event_group = $event->get_group;	
					$plugin_event_box->pack_start($event,FALSE,FALSE,0);
				}	

			$plugin_event_frame->add($plugin_event_box);
			$plugin_box->pack_start($plugin_event_frame,FALSE,FALSE,5);	

			# Timeout
			my $plugin_timeout_frame = Gtk2::Frame->new("Timeout");
			$plugin_timeout_frame->set_shadow_type('none');
			my $plugin_timeout_box = Gtk2::VBox->new(FALSE,0);
				my $timeout_entry = Gtk2::Entry->new_with_max_length(3);
				$timeout_entry->set_text($current_plugin->timeout);
				$plugin_timeout_box->pack_start($timeout_entry,FALSE,FALSE,0);			
			$plugin_timeout_frame->add($plugin_timeout_box);
			$plugin_box->pack_start($plugin_timeout_frame,FALSE,FALSE,5);

			# Save Button		

			my $plugin_save_frame = Gtk2::Frame->new();
			$plugin_save_frame->set_shadow_type('none');
			my $plugin_save_box = Gtk2::HBox->new(FALSE,0);

				my $plugin_save_button = Gtk2::Button->new_from_stock("gtk-save");
				$plugin_save_button->signal_connect('clicked' => sub {
					# generate updated profile
					print "Save Button Pressed\n";
					$current_plugin->runlevel($runlevel_entry->get_text);
					$current_plugin->timeout($timeout_entry->get_text);


					&save_plugin($current_plugin, $default_plugin);
					
				});
				$plugin_save_box->pack_start($plugin_save_button, FALSE,FALSE,0);

			$plugin_save_frame->add($plugin_save_box);
			$plugin_box->pack_start($plugin_save_frame,FALSE,FALSE,5);
					
		$plugin_tab->add($plugin_box);


		# top menu tabs
		
		my $tabs_plugin = Gtk2::MenuItem->new_with_mnemonic("Plugin: $default_plugin");
		$tabs_plugin->signal_connect('activate' => sub {
			$nb->set_current_page($nb->page_num($plugin_tab));
					});
		$tabs_menu->append($tabs_plugin);
		$tabs_menu->show_all;

		# plugin Information Tab
		my $plugin_tab_box = Gtk2::HBox->new(FALSE,0);

			my $pluginlabel =Gtk2::Label->new("Plugin: $default_plugin");
			$plugin_tab_box->pack_start($pluginlabel,FALSE,FALSE,0);		

			my $pluginbutton = Gtk2::Button->new('');
			$pluginbutton->set_image(Gtk2::Image->new_from_stock('gtk-close','menu'));
			$pluginbutton->set_relief('none');
			$pluginbutton->signal_connect('clicked' => sub {
				$nb->remove($plugin_tab);
				$tabs_menu->remove($tabs_plugin);
			});
			$plugin_tab_box->pack_start($pluginbutton,FALSE,FALSE,0);
			$plugin_tab_box->show_all();

		$nb->append_page($plugin_tab, $plugin_tab_box);
		$plugin_tab->show_all();
		$nb->set_current_page($nb->page_num($plugin_tab));
}
#######################################################################
# function save_plugin - saves plugin config file
#	Arguments: Plugin

sub save_plugin {
	print "Saving Plugin...\n";
	my $plugin=shift(@_);
	my $plugin_name =shift(@_);

	my $monitor = $plugin->monitor;
	my $offline = $plugin->offline;
	my $runlevel = $plugin->runlevel;
	my $event = $plugin->event;
	my $timeout = $plugin->timeout;

	my $plugin_path = "$basedir/plugins/$plugin_name/plugin.conf";

	#print "My path is: $plugin_path";

	if(-e "$plugin_path") {
		open(DAT, $plugin_path) or lprint(2,0, "Couldn't open plugin: $plugin_name");
		my @raw_data=<DAT>;
		close(DAT);

		#now let's add update information to the file
		foreach (@raw_data) {
			if(/\$monitor/) {$_="\$monitor=\"$monitor\";"; }
			if(/\$runlength/) {$_="\$runlength=\"$runlength\";"; }
			if(/\$offline/) {$_="\$offline=\"$offline\";"; }
			if(/\$runlevel/) {$_="\$runlevel=\"$runlevel\";"; }
			if(/\$event/) {$_="\$event=\"$event\";"; }
			if(/\$timeout/) {$_="\$timeout=\"$timeout\";"; }			
		}

		#print @raw_data;

		open(DAT, ">$plugin_path") || lprint(2,0, "Couldn't save plugin: $plugin_name");
		print DAT @raw_data;
		close(DAT);
	}
	else {
		lprint(2,0,"Plugin $plugin_name does not seem to exist");
	}

	# open or create profile for writing
}


#######################################################################
# function run_plugin - takes care of running individual plugin
#	Arguments: plugin_name

sub run_plugin {
	my $plugin_name = shift(@_);

	my $interface;

	print "Running $plugin_name\n";

	my $plugin_dialog = Gtk2::Dialog->new("$plugin_name", $window,'destroy-with-parent');
	my $plugin_label = Gtk2::Label->new("Please Note: Try to to fill in as much\n information as possible below\n to make the selected plugin work.");
	$plugin_dialog->vbox->add($plugin_label);

	# Interface Selection
	$plugin_dialog->vbox->add(Gtk2::Label->new("Select Interface"));
	my $cb_interface = Gtk2::ComboBox->new_text;
	
	foreach(keys %interface) {
		$cb_interface->append_text("$_");
	}

	$cb_interface->signal_connect('changed' => sub{
		$interface = $cb_interface->get_active_text;
		print $interface;
	});
	$cb_interface->set_active(0);
	$plugin_dialog->vbox->add($cb_interface);

	# Add a separator
	#$plugin_dialog->vbox(Gtk2::Separator->new());

	# SSID Entry
	$plugin_dialog->vbox->add(Gtk2::Label->new("AP's SSID"));
	my $plugin_ssid = Gtk2::Entry->new();
	$plugin_dialog->vbox->add($plugin_ssid);

	# BSSID Entry
	$plugin_dialog->vbox->add(Gtk2::Label->new("AP's BSSID"));
	my $plugin_bssid = Gtk2::Entry->new();
	$plugin_dialog->vbox->add($plugin_bssid);

	# Nick Entry
	$plugin_dialog->vbox->add(Gtk2::Label->new("Interface Nick"));
	my $plugin_nick = Gtk2::Entry->new();
	$plugin_dialog->vbox->add($plugin_nick);

	# Run the plugin
	my $run_plugin = Gtk2::Button->new("Run");
	$run_plugin->signal_connect('button-release-event' => sub{
		print "Loading plugin..\n";

	############## FIRST GET PLUGIN CONFIGURATION #########################

	# These are what we get from the plugin config file
	use vars qw($name $bin $version $monitor $runlength $offline $runlevel $event $timeout);

	my $return;
	my $plugins;
		my $plugin_config="$plugindir/$plugin_name/$pluginext";
		if(-r $plugin_config) {
			unless ($return = do $plugin_config) {
				warn "  [!] Couldn't parse $plugin_config: $@" if $@;
				warn "  [!] Couldn't run $plugin_config: $!"   unless defined $return;
				warn "  [!] Couldn't run $plugin_config"       unless $return;
				next;
			}

			$timeout=30 if(!defined($timeout));

			$plugins=Plugin->new();
			# TODO validate this data.
			$plugins->populate($name, $bin, $version, $monitor, $runlength, $offline, $runlevel, $event, $plugin_name, $timeout);
			
		} else {
			lprint(2, 1, "Can't find the configured plugin\n\t(Trying $plugin_config)\n");
		}


	############## EXECUTE PLUGIN #################
			my $bin_path = $plugins->bin;
			
			my @args=("$plugindir/$plugin_name/$bin_path", "-v", "0.1");

			push @args, "-i $interface";

			# Check for SSID
			if($plugin_ssid->get_text) {
				my $ssid = $plugin_ssid->get_text;
				push @args, "-s $ssid";
			}

			# Check for BSSID
			if($plugin_bssid->get_text) {
				my $bssid = $plugin_bssid->get_text;
				push @args, "-b $bssid";
			}

			# Check for Nickname
			if($plugin_nick->get_text) {
				my $nick = $plugin_nick->get_text;
				push @args, "-n $nick";
			}

			lprint(0,3,"Executing Plugin: @args\n");

			# Get output from wicrawl
			#$fh = FileHandle->new;
			#open($fh, "-|", "@args") or lprint(0,3,"\nCouldn't open\n");

			$fh = new IO::Pipe;
			$fh->reader("@args");

			$helper_tag = Gtk2::Helper->add_watch(fileno $fh, 'in', sub {
					&watch_callback($fh);
			});

	});
	$plugin_dialog->vbox->add($run_plugin);

	$plugin_dialog->signal_connect (response => sub { $_[0]->destroy });
	$plugin_dialog->show_all;
}

#######################################################################
# function preferences_tab - function generates overall gui config tab
#

sub preferences_tab {
	my $preferences_tab = Gtk2::Frame->new;
	
	# Preferences
		my $preferences_box = Gtk2::HBox->new(FALSE,0);

		# Profile Scheduling
		my $preferences_theme_frame = Gtk2::Frame->new("Themes");
		$preferences_theme_frame->set_shadow_type('none');
		my $preferences_theme_box = Gtk2::VBox->new(FALSE,0);

		my $preferences_theme_group;
			foreach (@themes) {
				my $label = $_;
				$theme = Gtk2::RadioButton->new($preferences_theme_group, "$label");
				$theme->signal_connect('toggled' => sub {
					$preferences->theme($label);
				});
				if ($preferences->theme eq "$label") {
					$theme->set_active(TRUE);
				} else {
					$theme->set_active(FALSE);
				}
				$preferences_theme_group = $theme->get_group;	
				$preferences_theme_box->pack_start($theme,FALSE,FALSE,0);
			}		

		$preferences_theme_frame->add($preferences_theme_box);
		$preferences_box->pack_start($preferences_theme_frame,FALSE,FALSE,5);	



		# Verbosity and Save
		my $preferences_verbosity_frame = Gtk2::Frame->new();
		$preferences_verbosity_frame->set_shadow_type('none');
		my $preferences_verbosity_box = Gtk2::VBox->new(FALSE,0);
			
			# Plugin Engine Verbosity
			my $verbosity_pe_label = Gtk2::Label->new("Plugin Engine Verbosity (0-3)");
			$preferences_verbosity_box->pack_start($verbosity_pe_label, FALSE, FALSE, 5);

			my $verbosity_pe_entry = Gtk2::Entry->new;
			$verbosity_pe_entry->set_text($preferences->verbosity_pluginengine);
			$preferences_verbosity_box->pack_start($verbosity_pe_entry, FALSE, FALSE, 5);

			# GUI Verbosity
			my $verbosity_ui_label = Gtk2::Label->new("GUI Verbosity (0-3)");
			$preferences_verbosity_box->pack_start($verbosity_ui_label, FALSE, FALSE, 5);

			my $verbosity_ui_entry = Gtk2::Entry->new;
			$verbosity_ui_entry->set_text($preferences->verbosity_ui);
			$preferences_verbosity_box->pack_start($verbosity_ui_entry, FALSE, FALSE, 5);

			my $preferences_save_button = Gtk2::Button->new_from_stock("gtk-save");
			$preferences_save_button->signal_connect('clicked' => sub {
				# generate updated profile
				lprint(1,1, "Selected Theme will be applied after you restart wicrawl\n");
				# for now just save default theme name to the preferences
				$preferences->verbosity_pluginengine($verbosity_pe_entry->get_text);
				$preferences->verbosity_ui($verbosity_ui_entry->get_text);
				&save_preferences($preferences);
			});
			$preferences_verbosity_box->pack_start($preferences_save_button, FALSE, FALSE, 5);

			

		$preferences_verbosity_frame->add($preferences_verbosity_box);
		$preferences_box->pack_start($preferences_verbosity_frame,FALSE,FALSE,5);


	$preferences_tab->add($preferences_box);

	# top menu tabs
	
	my $tabs_preferences = Gtk2::MenuItem->new_with_mnemonic("Preferences");
	$tabs_preferences->signal_connect('activate' => sub {
		$nb->set_current_page($nb->page_num($preferences_tab));
				});
	$tabs_menu->append($tabs_preferences);
	$tabs_menu->show_all;
		# preferences Information Tab
	my $preferences_tab_box = Gtk2::HBox->new(FALSE,0);
			my $preferenceslabel =Gtk2::Label->new("Preferences");
		$preferences_tab_box->pack_start($preferenceslabel,FALSE,FALSE,0);		
			my $preferencesbutton = Gtk2::Button->new('');
		$preferencesbutton->set_image(Gtk2::Image->new_from_stock('gtk-close','menu'));
		$preferencesbutton->set_relief('none');
		$preferencesbutton->signal_connect('clicked' => sub {
			$nb->remove($preferences_tab);
			$tabs_menu->remove($tabs_preferences);
		});
		$preferences_tab_box->pack_start($preferencesbutton,FALSE,FALSE,0);
		$preferences_tab_box->show_all();
		$nb->append_page($preferences_tab, $preferences_tab_box);

	$preferences_tab->show_all();
	$nb->set_current_page($nb->page_num($preferences_tab));

}

#######################################################################
# function save_preferences - saves preferences to file
#	Arguments: Plugin

sub save_preferences {
	print "Saving Preferences...\n";
	my $preferences=shift(@_);

	my $preferences_path = "$confdir/wicrawl-gtk.conf";
	my $theme = $preferences->theme;
	my $verbosity_pluginengine = $preferences->verbosity_pluginengine;
	my $verbosity_ui = $preferences->verbosity_ui;


	if(-e "$preferences_path") {
		open(DAT, $preferences_path) or lprint(2,0, "Couldn't open preferences: $preferences_path");
		my @raw_data=<DAT>;
		close(DAT);

		#now let's add update information to the file
		foreach (@raw_data) {
			if(/\$theme/) {$_="\$theme=\"$theme\";\n"; }	
			if(/\$verbosity_pluginengine/) {$_="\$verbosity_pluginengine=\"$verbosity_pluginengine\";\n"; }	
			if(/\$verbosity_ui/) {$_="\$verbosity_ui=\"$verbosity_ui\";\n"; }	
		}

		#print @raw_data;

		open(DAT, ">$preferences_path") || lprint(2,0, "Couldn't save preferences: $preferences_path");
		print DAT @raw_data;
		close(DAT);
	}
	else {
		lprint(2,0,"Plugin $preferences_path does not seem to exist");
	}

	# open or create profile for writing
}
#######################################################################
# function open_output - opens output from file
#	Arguments: None

sub open_output {
	my $file_chooser = Gtk2::FileChooserDialog->new (
								'Open', undef, 'open',
								'gtk-cancel' => 'cancel',
								'gtk-ok' => 'ok'
						);
	$file_chooser->add_filter(ret_xml_filter());
	
	my $filename;

	if('ok' eq $file_chooser->run){
		$filename = $file_chooser->get_filename;
		lprint(1,1,"Opening filename $filename");
	}

	$file_chooser->destroy;

	# now let's load the file

	# Load ap file
	if($filename =~ "wicrawl_discovery") {
		$apcoredb = $filename;
		&show_data();

		#attempt to find the plugins output file as well
		$filename =~ s/wicrawl_discovery/wicrawl_plugins-output/;
		$filename =~ s/xml\.(\w+)/xml/;
		print "Checking $filename";
		if((defined $filename) && (-f $filename)) {
			$plugincoredb = $filename;
			&get_plugins();
		}
	}

	# Load plugins file
	if($filename =~ "wicrawl_plugins-output") {
		$plugincoredb = $filename;
		&get_plugins();
	}

}
#######################################################################
# function ret_xml_filter - filters out only xml files

sub ret_xml_filter {
	my $filter = Gtk2::FileFilter->new();
	$filter->set_name("text/xml");
	$filter->add_mime_type("text/xml");

	return $filter;
}

#######################################################################
# function save_output - saves output to file
#	Arguments: Output type

sub save_output {
	
	my $type = "xml";

	my $file_chooser = Gtk2::FileChooserDialog->new (
								'Save', undef, 'save',
								'gtk-cancel' => 'cancel',
								'gtk-ok' => 'ok'
						);

	# suggest default save file
	my $timestamp = time;
	$file_chooser->set_current_name("wicrawl-report-$timestamp.xml");


	# extra save type selector
	my $hbox = Gtk2::HBox->new(FALSE,0);

	my $label = Gtk2::Label->new("Select Type:      ");
	$hbox->pack_start($label,FALSE,FALSE,0);

	my $cb = Gtk2::ComboBox->new_text;
	$cb->append_text("xml");
	$cb->append_text("html");
	$cb->append_text("txt");
	$cb->signal_connect('changed' =>sub {
		$type = $cb->get_active_text;
		$file_chooser->set_current_name("wicrawl-report-$timestamp.$type");
	});
	$cb->set_active(0);

	$hbox->pack_start($cb,TRUE,TRUE,0);
	$hbox->show_all;

	$file_chooser->set_extra_widget($hbox);



	my $filename;
	if ('ok' eq $file_chooser->run){
		$filename = $file_chooser->get_filename;
		lprint (1,1,"Saving filename $filename\n");
	}

	$file_chooser->destroy;

	if (defined $filename) {
		if (-f $filename) {
			my $overwrite = show_message_dialog( $window, 'question',
													'Overwrite existing file:'."<b>\n$filename</b>",
													'yes-no'
											);
			return if($overwrite eq 'no');
		}
		
	}

	if(defined $apcoredb) {
		if(-f $apcoredb) {

			open(SAV, ">$filename") || lprint(2,0,"Couldn't save $filename");

			
			########################### XML OUTPUT #############################
			if($type eq "xml") {
				open(DAT, $apcoredb) or lprint(2,0, "Couldn't open $apcoredb");
				my @raw_data=<DAT>;
				close(DAT);
				print SAV @raw_data;
			}
			
			####################################################################
			# we have to actually generate the report
		        else {
				my $output;
				my @APS = &get_ap;
				my $wepcount = 0;
				my $packets = 0;
				my $totalap = 0;
				my $haveinternet = 0;
				my $newap = 0;
				my $ip = 0;
				my $associated = 0;

				my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
				$year += 1900;
				my $timestamp = "$mon-$mday-$year $hour:$min:$sec";


				############################## HTML OUTPUT ########################
				if($type eq "html") {

					my $output = "<html>\n";
					$output .= "<head>\n";
					$output .= "<title>Wicrawl Report - Generated on $timestamp</title>\n";
					$output .= "</head>\n";
					$output .= "<body>\n";
					$output .= "<h1>Wicrawl Report - Generated on $timestamp</h1>\n";
					$output .= "<table border='1'>\n";
					$output .=	"<tr><td>SSID</td><td>BSSID</td><td>Time</td><td>Packets</td><td>Plugin</td><td>Event</td><td>Timestamp</td><td>Encryption</td><td>Power</td><td>Channel</td><td>Latitude</td><td>Longitude</td></tr>";

					foreach (@APS) {
						$output .= "	<tr>\n";
						
						$totalap++;
						$packets += $_->{PACKETS};
						if($_->{ENCRYPTION} eq "WEP") {$wepcount++}
						if($_->{EVENT} eq "have-internet") {$haveinternet++}
						if($_->{EVENT} eq "new-ap") {$newap++}
						if($_->{EVENT} eq "associated") {$associated++}
						if($_->{EVENT} eq "have-ip") {$ip++}

						#fix timestamp
						my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($_->{TIMESTAMP});
						$year += 1900;
						my $timestamp = "$mon-$mday-$year $hour:$min:$sec";

						#get correct color for the row
						my $color = "black";
						my $event = $_->{EVENT};
						if ($event eq "new-ap") {
							$color = "red";
						}
						elsif ($event eq "associated") {
							$color = "orange";
						}
						elsif ($event eq "have-internet") {
							$color = "darkgreen";
						}
						else {
							$color = "black";
						}

						$output .= "		<td><font color='$color'>$_->{SSID}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{BSSID}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{TIME}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{PACKETS}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{PLUGIN}</font></td>\n";
						$output .=  "		<td><font color='$color'>$_->{EVENT}</font></td>\n";
						$output .= "		<td><font color='$color'>$timestamp</font></td>\n";
						$output .=  "		<td><font color='$color'>$_->{ENCRYPTION}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{POWER}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{CHANNEL}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{LATITUDE}</font></td>\n";
						$output .= "		<td><font color='$color'>$_->{LONGITUDE}</font></td>\n";
		
						$output .= "</tr>\n\n";
					}
					$output .= "</table>\n\n";

					# formatted plugins output
					$output .= "<h2>Plugins Output</h2>\n";
					$output .= &plugin_html_output;

					if($totalap) {

						my $ratio = int($wepcount*100/$totalap);
	
						$output .= "<br>\n";
						$output .= "<h2>Statistics</h2>\n";
						$output .= "<table>\n";
						$output .= "	<tr>\n";
						$output .= "		<td>Total APs: </td><td>$totalap</td>\n";
						$output .= "		<td>Encrypted: </td><td>$wepcount</td>\n";
						$output .= "		<td>Ratio: </td><td>$ratio%</td>";
						$output .= "		<td>Packets: </td><td>$packets</td>\n";
						$output .= "	</tr>\n";
						$output .= "</table>\n";

						#colorbar
						my $width = 100;
						my $colorbar_newap = int($newap/$totalap*$width);
						my $colorbar_associated = int($associated/$totalap*$width);
						my $colorbar_ip = int($ip/$totalap*$width);
						my $colorbar_internet = int($haveinternet/$totalap*$width);

						# now let's generate a bar
						my $colorbar_markup = "<br><br>\n<center>\n";
						$colorbar_markup .= "<table border='0' cellspacing='0' cellpadding='0'><tr bgcolor='black'><td bgcolor = 'black'>";

						my $unknown_state = $width - $colorbar_newap - $colorbar_associated - $colorbar_ip - $colorbar_internet;
						my $unknown_number = $totalap - $newap - $associated - $ip - $haveinternet;
						for(my $i=0; $i < $unknown_state; $i++) { 
							if($i == int($unknown_state/2)) {
								if($unknown_number) {
									$colorbar_markup .= "<font color='white'>$unknown_number</font>"; 
								}
							}
							else {$colorbar_markup .= "&nbsp"; }
						}
						$colorbar_markup .= "</td>";

						#newap info
						$colorbar_markup .= "<td bgcolor = 'red'>";
						for(my $i = 0; $i < $colorbar_newap; $i++) { 
							if($i == int($colorbar_newap/2)) {$colorbar_markup .= "<font color='white'>$newap</font>"; }
							else {$colorbar_markup .= "&nbsp"; } 
						}
						$colorbar_markup .= "</td>";
			
						#associated info
						$colorbar_markup .= "<td bgcolor = 'orange'>";
						for(my $i = 0; $i < $colorbar_associated; $i++) { 
							if($i == int($colorbar_associated/2)) {$colorbar_markup .= "<font color='white'>$associated</font>"; }
							else {$colorbar_markup .= "&nbsp"; } 
						}
						$colorbar_markup .= "</td>";

						#have-ip info
						$colorbar_markup .= "<td bgcolor = 'blue'>";
						for(my $i = 0; $i < $colorbar_ip; $i++) { 
							if($i == int($colorbar_ip/2)) {$colorbar_markup .= "<font color='white'>$ip</font>"; }
							else {$colorbar_markup .= "&nbsp"; } 
						}
						$colorbar_markup .= "</td>";
		
						#have-internet info
						$colorbar_markup .= "<td bgcolor = 'darkgreen'>";
						for(my $i = 0; $i < $colorbar_internet; $i++) { 
							if($i == int($colorbar_internet/2)) {$colorbar_markup .= "<font color='white'>$haveinternet</font>"; }
							else {$colorbar_markup .= "&nbsp"; } 
						}
						$colorbar_markup .= "</td></tr></table></center>\n";
		
						$output .= $colorbar_markup;

						# Add explanation of color coding above
						$output .= "<br><h2>Legend</h2>\n";
						$output .= "<table>\n";
						$output .= "<tr><td bgcolor='black'><font color='white'>Unknown State</font></td></tr>\n";
						$output .= "<tr><td bgcolor='red'><font color='white'>NewAP</font></td></tr>\n";
						$output .= "<tr><td bgcolor='orange'><font color='white'>Associated</font></td></tr>\n";
						$output .= "<tr><td bgcolor='blue'><font color='white'>GotIP</font></td></tr>\n";
						$output .= "<tr><td bgcolor='darkgreen'><font color='white'>Internet</font></td></tr>\n";
						$output .= "</table>\n";
						
	

					}
					
					$output .= "</body>\n";
					$output .= "</html>\n";

					# now print to file
					print SAV $output;

				}

				if($type eq "txt") {
	

					$output .= "Wicrawl Report - Generated on $timestamp\n";
					$output .= "================================================\n\n\n";


					my $tb = Text::TabularDisplay->new(
						"SSID", "BSSID" , "Time", "Packets", "Plugin", "Event", "Timestamp", "Encryption", "Power", "Channel", "Latitude", "Longitude"
					);					


					foreach (@APS) {						
						$totalap++;
						$packets += $_->{PACKETS};
						if($_->{ENCRYPTION} eq "WEP") {$wepcount++}
						if($_->{EVENT} eq "have-internet") {$haveinternet++}
						if($_->{EVENT} eq "new-ap") {$newap++}
						if($_->{EVENT} eq "associated") {$associated++}
						if($_->{EVENT} eq "have-ip") {$ip++}

						$tb->add($_->{SSID},
							$_->{BSSID},
							$_->{TIME},
							$_->{PACKETS},
							$_->{PLUGIN},
							$_->{EVENT},
							$timestamp,
							$_->{ENCRYPTION},
							$_->{POWER},
							$_->{CHANNEL},	
							$_->{LATITUDE},
							$_->{LONGITUDE})

					}
					$output .= $tb->render;

					$output .= "\n\nPlugin Output\n";
					$output .= "=============\n";

					$output .= &plugin_txt_output;

					my $ratio = int($wepcount*100/$totalap);

					$output .= "\n\nStatistics\n";
					$output .= "==========\n\n";
					$output .= "    Total APs: $totalap\n";
					$output .= "    Encrypted: $wepcount\n";
					$output .= "        Ratio: $ratio%\n";
					$output .= "      Packets: $packets\n";
					$output .= "Have Internet: $haveinternet\n";
					$output .= "       NewAPs: $newap\n";
					$output .= "   Associated: $associated\n";
					$output .= "      Have IP: $ip\n";
				
					#now print to file
					print SAV $output;

				}
			}

			close(SAV);
		}
	}

}

sub plugin_html_output() {

	my $output = "";

	my(@accesspoint, @PLUGINS);
	my $XML; 
	my $count=0;

	$XML = XML::Smart->new($plugincoredb);

	my $size=(stat("$plugincoredb"))[7];

	# We only want to search through the xml file if it exists
	# Otherwise it will create an empty entry
	if ((defined($size)) && ($size >= 122)) {

		if($cutroot) {
			$XML = $XML->cut_root;
		}

		@accesspoint = @{$XML->{"accesspoint"}};

		$output .= "<ul>";

		foreach(@accesspoint) {
				my $ssid = $_->{ssid};
				my $bssid = $_->{bssid};
	
				$output .= "<li>$ssid ($bssid)</li>\n";
	
				my @plugin = @{$_->{"plugin"}};
		
				$output .= "   <ul>\n";
	
				my $current_run =-1;
				my $run_tree;
		
				foreach my $plugin (@plugin) {
						my $plugin_run = $plugin->{run};
						my $plugin_name = $plugin->{name};
						my $plugin_output = decode_base64($plugin->{output});

						if($current_run != $plugin_run) {
								if($current_run >= 0) {
										$output .= "	</ul><ul>\n";
								}
								$output .= "	<li>Run $plugin_run\n";
								$current_run = $plugin_run;
						}

						$output .= "		<ul>\n";
						$output .= "		<li>$plugin_name<br><pre>$plugin_output</pre>\n";
						$output .= "		</ul>\n";
				}
		
				$output .= "</ul>\n";
		}
		$output .= "</ul>";

	} else {
		#print "Couldn't open $plugincoredb";
	}
	return $output;
}

sub plugin_txt_output() {

	my $output = "";

	my(@accesspoint, @PLUGINS);
	my $XML; 
	my $count=0;

	$XML = XML::Smart->new($plugincoredb);

	my $size=(stat("$plugincoredb"))[7];

	# We only want to search through the xml file if it exists
	# Otherwise it will create an empty entry
	if ((defined($size)) && ($size >= 122)) {

		if($cutroot) {
			$XML = $XML->cut_root;
		}

		@accesspoint = @{$XML->{"accesspoint"}};

		foreach(@accesspoint) {
				my $ssid = $_->{ssid};
				my $bssid = $_->{bssid};
	
				$output .= " + $ssid ($bssid)\n";
	
				my @plugin = @{$_->{"plugin"}};
		
	
				my $current_run =-1;
				my $run_tree;
		
				foreach my $plugin (@plugin) {
						my $plugin_run = $plugin->{run};
						my $plugin_name = $plugin->{name};
						my $plugin_output = decode_base64($plugin->{output});
						my @plugin_output = split(/\n/, $plugin_output);

						if($current_run != $plugin_run) {
								$output .= " |\n";
								$output .= " +---+ Run $plugin_run\n";
								$current_run = $plugin_run;
						}
						$output .= "     |\n";
						$output .= "     +---+ $plugin_name\n";
						$output .= "          \n";
						foreach (@plugin_output) {
						$output .= "          $_ \n";
						}
						$output .= "\n";
				}		
		}

	} else {
		#print "Couldn't open $plugincoredb";
	}


	return $output;
}

sub show_message_dialog {
#---------------------------------------------------
#you tell it what to display, and how to display it
#$parent is the parent window, or "undef"
#$icon can be one of the following: a) 'info'
#                   b) 'warning'
#                   c) 'error'
#                   d) 'question'
#$text can be pango markup text, or just plain text, IE the message
#$button_type can be one of the following:  a) 'none'
#                       b) 'ok'
#                       c) 'close'
#                       d) 'cancel'
#                       e) 'yes-no'
#                       f) 'ok-cancel'
#---------------------------------------------------

my ($parent,$icon,$text,$button_type) = @_;
  
my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
                    [qw/modal destroy-with-parent/],
                    $icon,
                    $button_type,
                    sprintf "$text");
    my $retval = $dialog->run;
    $dialog->destroy;
    return $retval;
}

# vim:ts=2:sw=2:sts=0
