#!/usr/bin/python -OO
#
#   $Id: wifi-radar 71 2006-09-26 15:58:54Z finley $
#    vi:set filetype=python noet:
#
#	A wireless profile manager for Linux
#
#   Originally created for x1000 Linux:
#	    http://x1000.bitbuilder.com
#
#   Created by:
#	    Ahmad Baitalmal <ahmad@baitalmal.com>
#
#   Maintained by:
#	    Brian Elliott Finley <brian@thefinleys.com>
#	
#   License:
#       GPL
#
#	http://www.bitbuilder.com/wifi_radar
#	http://svn.systemimager.org
#
#	See AUTHORS file for more contributors.
#	See ChangeLog file for, well, changes.
#

import time, os, signal, sys, re, ConfigParser, thread, socket
WIFI_RADAR_VERSION = "0.0.0"

if __debug__:
	print '__debug__ is True'
	# NOTE: Remove the '-00' from '#!/usr/bin/python -OO' in the first line to 
	#       turn on debugging.

####################################################################################################
# Defaults, these may get overridden by values found in the conf file
# The interface you use
INTERFACE		= "eth1"

# How long should the scan last?
SCAN_TIMEOUT	= "5"

# Should I speak up when connecting to a network? (If you have a speach command)
SPEAK_UP		= False

# You may set this to true for cards that require a "commit" command with iwconfig
COMMIT_REQUIRED	= False

# You may set this to true for cards that require the interface to be brought up first
IFUP_REQUIRED	= False

#
# Where the conf file should live could be different for your distro.  Please change
# at install time with "make install sysconfdir=/etc/wifi-radar" or similar. -BEF-
#
CONF_FILE		 = "/etc/wifi-radar/wifi-radar.conf"

IWLIST_COMMAND	 = "LC_MESSAGES=C iwlist"
IWCONFIG_COMMAND = "LC_MESSAGES=C iwconfig"
IFCONFIG_COMMAND = "LC_MESSAGES=C ifconfig"
ROUTE_COMMAND	 = "LC_MESSAGES=C route"

# X1000 Linux has a say command (text to speach) to accounce connecting to networks.
# Set the SPEAK_UP to false if you do not have or want this.
SAY_COMMAND		= "say"

def which( command ):
    for i in os.environ["PATH"].split(":"):
        FILE = "%s/%s" % ( i, command )
        if os.path.isfile( FILE ):
            return FILE

#
# List of supported DHCP clients in order of preference
#
POSSIBLE_DHCP_CLIENTS = "dhcpcd dhclient3 dhclient pump"
DHCP_TIMEOUT	= 30
HOSTNAME = socket.gethostname()

for i in POSSIBLE_DHCP_CLIENTS.split():
	DHCP_COMMAND = which( i )
	if DHCP_COMMAND:
	
		if i == "dhcpcd":
		    DHCP_PIDFILE        = "/var/run/dhcpcd-%s.pid" % INTERFACE
			#
		    # See "man dhcpcd-bin" or "man dhcpcd" for additional options.
			#
		    # Additional options can be set in the dhcpcd config file, which
			# often lives here: "/etc/dhcpc/config".
			#
		    DHCP_ARGS           = "-h %s -t %s" % (HOSTNAME, DHCP_TIMEOUT)
		    DHCP_KILL_COMMAND   = DHCP_COMMAND + " -k " 
		    break
		
		elif (i == "dhclient") or (i == "dhclient3"):
		    #
		    # dhclient v2 or v3?
		    #
			#f = os.popen( scan_command, "r" )
			cmd = i + ' --version 2>&1'
			print "%s" % cmd
			f = os.popen( cmd , 'r' )
			s = f.read()
			f.close()
			if re.search('-V3\.', s):
				#
				# dhclient v3
				#
				# Usage: dhclient [-1dqr] [-nw] [-p <port>] [-s server]
				#	 [-cf config-file] [-lf lease-file][-pf pid-file] [-e VAR=val]
				# 	[-sf script-file] [interface]
				#
				DHCP_PIDFILE        = "/var/run/dhclient.%s.pid" % INTERFACE
				DHCP_ARGS           = "-1 -pf " + DHCP_PIDFILE + " -lf /var/run/dhclient.%s.leases" % INTERFACE
				DHCP_KILL_COMMAND   = DHCP_COMMAND + " -r " + DHCP_ARGS
				if __debug__:
					print 'Using dhclient v3 syntax'
			else:
				#
				# dhclient v2
				#
				# Usage: dhclient [-c] [-d] [-e] [-p <port>] [-lf lease-file]
				#   [-pf pidfile] [interface]
				#
				# Example:  dhclient -e -pf /var/run/dhclient.eth1.pid -lf /var/run/dhclient.eth1.leases eth1
				#
				DHCP_PIDFILE        = "/var/run/dhclient.%s.pid" % INTERFACE
				DHCP_ARGS           = "-e -pf " + DHCP_PIDFILE + " -lf /var/run/dhclient.%s.leases" % INTERFACE
				# There is no dhcp kill command for dhclient v2.  Let the "disconnect_interface" function handle it via pid.
				DHCP_KILL_COMMAND   = ""
				if __debug__:
					print 'Using dhclient v2 syntax'
			break

		elif i == "pump":
		    DHCP_PIDFILE        = "" # no pid file for pump
		    DHCP_ARGS           = "-i"
		    DHCP_KILL_COMMAND   = DHCP_COMMAND + " -r " + DHCP_ARGS + " " + INTERFACE
		    break


# WPA_SUPPLICANT
WPA_SUPPLICANT_COMMAND	= "/usr/sbin/wpa_supplicant"
WPA_SUPPLICANT_KILL_COMMAND=""
WPA_SUPPLICANT_CONF="/etc/wpa_supplicant/wpa_supplicant.conf"
WPA_DRIVER="ipw"
WPA_SUPPLICANT_PIDFILE	= "/var/run/wpa_supplicant.pid" 

#####################################
# Labels
USE_DHCP_LABEL	= "Automatic network configuration (DHCP)"
USE_IP_LABEL	= "Manual network configuration"
WIFI_SET_LABEL	= "WiFi Options"
POSTPRE_LABEL	= "Connection Commands"
USE_WPA_LABEL	= "Use WPA"
NO_WPA_LABEL	= "No WPA"
WIFI_MODES		= [ '', 'auto', 'Managed', 'Ad-Hoc', 'Master', 'Repeater', 'Secondary', 'Monitor' ]
WIFI_SECURITY	= [ '', 'open', 'restricted' ]
WIFI_CHANNELS	= [ '', 'auto', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14' ]
####################################################################################################

####################################################################################################
####################################################################################################
# Scan for a limited time, return ap names found
def scanning_thread( lock = None ):
	global access_points
	global main_radar_window
	global exit_flag
	global current_ip
	global current_ssid
	# Setup our essid pattern matcher
	essid_pattern		= re.compile( "ESSID\s*(:|=)\s*\"([^\"]+)\"", re.I | re.M  | re.S )
	protocol_pattern	= re.compile( "Protocol\s*(:|=)\s*IEEE 802.11\s*([abg]+)", re.I | re.M  | re.S )
	mode_pattern		= re.compile( "Mode\s*(:|=)\s*([^\n]+)", re.I | re.M  | re.S )
	enckey_pattern		= re.compile( "Encryption key\s*(:|=)\s*(on|off)", re.I | re.M  | re.S )
	signal_pattern		= re.compile( "Signal level\s*(:|=)\s*-?([0-9]+)", re.I | re.M  | re.S )
	# Access points we find will be added to the access_points dictionary
	scan_command 		= "%s %s scan" % ( IWLIST_COMMAND, INTERFACE )
	# Some cards neet to have the interface up to scan
	if IFUP_REQUIRED:
		os.spawnlp( os.P_WAIT, 'ifconfig', IFCONFIG_COMMAND, INTERFACE, "up" )
	trial = 0
	while True:
		# reset the signal strengths
		if __debug__:
			print ".",
		# Read data
		f = os.popen( scan_command, "r" )
		scandata = f.read()
		f.close()
		# get the current ip
		curr_ip = get_current_ip()
		if __debug__:
			print "Got current IP ", curr_ip
		if curr_ip:
			current_ip		= curr_ip
		else:
			current_ip		= 'None'
		# get the current ssid
		curr_ssid = get_current_ssid()
		if __debug__:
			print "Got current SSID ", curr_ssid
		if curr_ssid:
			current_ssid	= curr_ssid
		else:
			current_ssid	= 'None'
		# we may not be running in a thread
		try:
			lock.acquire()
		except:
			trial = trial + 1
			if trial > int( SCAN_TIMEOUT ):
				return
		if exit_flag:
			if __debug__:
				print "Ending scan"
			thread.exit()
			return
		for ap in access_points:
			access_points[ ap ]['signal'] = '0'
		# split the scan data based on the address
		hits = scandata.split( '- Address:' )
		for hit in hits:
			foundvalues = False
			apname		= ''
			protocol	= 'b'
			mode		= ''
			encrypted	= 'off'
			signal		= '0'
			m = essid_pattern.search( hit )
			if m:
				# we found an ssid
				foundvalues = True
				apname = m.groups()[1]
				m = protocol_pattern.search( hit )
				if m:
					protocol = m.groups()[1]
				m = mode_pattern.search( hit )
				if m:
					mode = m.groups()[1]
				m = enckey_pattern.search( hit )
				if m:
					encrypted = m.groups()[1]
				m = signal_pattern.search( hit )
				if m:
					signal = m.groups()[1]
				# Set the values we found
				if access_points.has_key( apname ):
					# We know this ssid, make it available
					access_points[ apname ]['available'] = True
				else:
					# Add it to the available networks
					ap = {}
					ap['known']		= False
					ap['available']	= True
					access_points[ apname ] = ap
				access_points[ apname ]['protocol']	= protocol
				access_points[ apname ]['mode']		= mode
				access_points[ apname ]['encrypted']= ( encrypted == 'on' )
				access_points[ apname ]['signal'] 	= signal
		try: lock.release()
		except:	pass
                if INTERFACE.find('ath') == 0:
                        time.sleep( 30 )
                else:
                        time.sleep( 0.5 )
	return

# Connects to the first matching network
def connect_to_preferred():
	global access_points
	global auto_profile_order
	found_one = False
	for ssid in auto_profile_order:
		ssid = ssid.strip()
		if 	access_points.has_key( ssid )	\
			and	access_points[ ssid ]['known'] \
			and access_points[ ssid ]['available']:
			found_one = True
			connect_to_network( ssid, None )
			break
	if not found_one:
		say( "No preferred network found" )
		if __debug__:
			print "   No preferred network found"
			print access_points

def get_current_ip():
	"""Returns the current IP if any by calling ifconfig"""
	ifconfig_info = os.popen( IFCONFIG_COMMAND + " " + INTERFACE, 'r' )
	# Be careful to the language (inet adr: in French for example)
	#
    # Hi Brian
    # 
    # I'm using wifi-radar on a system with German translations (de_CH-UTF-8).
    # There the string in ifconfig is inet Adresse for the IP which isn't
    # found by the current get_current_ip function in wifi-radar. I changed
    # the according line (#289; gentoo, v1.9.6-r1) to
    # >ip_re = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)')
    # which works on my system (LC_ALL=de_CH.UTF-8) and still works with LC_ALL=C.
    # 
    # I'd be happy if you could incorporate this small change because as now
    # I've got to change the file every time it is updated.
    # 
    # Best wishes
    # 
    # Simon
	ip_re = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)')
	for line in ifconfig_info:
		if ip_re.search( line ):
			return ip_re.search( line ).group(1)
	return False

def get_current_ssid():
	"""Returns the current SSID if any by calling iwconfig"""
	ifconfig_info = os.popen( IWCONFIG_COMMAND + " " + INTERFACE, 'r' )
	# Be careful to the language (inet adr: in French for example)
	essid_re = re.compile(r'ESSID\s*(:|=)\s*"([^"]*)"')
	for line in ifconfig_info:
		if essid_re.search( line ):
			return essid_re.search( line ).group(2)
	return False

def	connect_to_network( essid, status_win ):
	msg = "Connecting to the %s network" % essid
	say( msg )
	if __debug__:
		print "   %s" % msg
	profile = get_profile_from_conf_file( essid )
	if not profile:
		if __debug__:
			print "Unknown SSID"
		say( "Unknown SSID" )
		return
	# ready to dance
	# Let's run the prescript
	prescript = profile['prescript']
	if prescript.strip() != '':
		# got something to execute
		if __debug__:
			print "executing prescript:", prescript
		os.system( prescript )
	# Some cards neet to have the interface up
	if IFUP_REQUIRED:
		os.spawnlp( os.P_WAIT, 'ifconfig', IFCONFIG_COMMAND, INTERFACE, "up" )
	iwconfig_args = [ INTERFACE ]
	# Let's start with the ssid
	if __debug__:
		print "Setting essid ", essid
	iwconfig_args.append( 'essid' )
	iwconfig_args.append( '"%s"' % essid )
	iwconfig_args.append( 'nick' )
	iwconfig_args.append( '"%s"' % essid )
	#os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'essid', "%s" % essid )
	# Now we do the key
	key 	= profile['key']
	security= profile['security']
	if  key == '':
		key 	= 'off'
	else:
		key = "%s %s" % ( profile['security'], profile['key'], )
	if __debug__:
		print "Setting key ", key
	#os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'key', key )
	iwconfig_args.append( 'key' )
	iwconfig_args.append( key )
	# Now, the mode
	mode	= profile['mode']
	if mode != '':
		if __debug__:
			print "Setting mode ", mode
		#os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'mode', mode )
		iwconfig_args.append( 'mode' )
		iwconfig_args.append( mode )
	# Now the channel
	channel	= profile['channel']
	if channel != '':
		if __debug__:
			print "Setting channel ", channel
		#os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'channel', channel )
		iwconfig_args.append( 'channel' )
		iwconfig_args.append( channel )
	# Some cards require a commit
	if COMMIT_REQUIRED:
		if __debug__:
			print "Setting commit "
		#os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'commit' )
		iwconfig_args.append( 'commit' )
	if __debug__:
		print "iwconfig_args %s " % ( iwconfig_args, )
	iwconfig_command = IWCONFIG_COMMAND + ' ' + ' '.join( iwconfig_args )
	#os.spawnvp( os.P_WAIT, 'iwconfig', iwconfig_args )
	if __debug__:
		print "iwconfig_command ", iwconfig_command
	os.system( iwconfig_command )
	# Now normal network stuff
	# Kill off any existing DHCP clients running
	if os.access( DHCP_PIDFILE, os.R_OK):
		if __debug__:
			print "Killing existing DHCP..."
		try:
			if DHCP_KILL_COMMAND != '':
				if __debug__:
					print DHCP_KILL_COMMAND
				os.popen( DHCP_KILL_COMMAND )
			else:
				os.kill( int(open(DHCP_PIDFILE, mode='r').readline()), signal.SIGTERM )
		except OSError:
			print "Stale pid file.  Removing"
			os.remove( DHCP_PIDFILE )
		if os.path.isfile( DHCP_PIDFILE ):
			print "Stale pid file.  Removing"
			os.remove( DHCP_PIDFILE )
	if os.access( WPA_SUPPLICANT_PIDFILE, os.R_OK):
		if __debug__:
			print "Killing existing WPA_SUPPLICANT..."
		try:
			if not WPA_SUPPLICANT_KILL_COMMAND == '':
				os.spawnlp( os.P_WAIT, WPA_SUPPLICANT_KILL_COMMAND, WPA_SUPPLICANT_KILL_COMMAND )
			os.kill( int(open(WPA_SUPPLICANT_PIDFILE, mode='r').readline()), signal.SIGTERM )
		except OSError:
		       	print "Stale pid file.  Removing"
			os.remove( WPA_SUPPLICANT_PIDFILE )
		if os.path.isfile( WPA_SUPPLICANT_PIDFILE ):
			print "Stale pid file.  Removing"
			os.remove( WPA_SUPPLICANT_PIDFILE )
	use_wpa = profile['use_wpa']
	if use_wpa :
		wpa_options = list()
		wpa_options.append( WPA_SUPPLICANT_COMMAND )
		wpa_args = WPA_SUPPLICANT_ARGS % ( INTERFACE, profile['wpa_driver'] )
		wpa_args = "-B -i " + INTERFACE + " -c " + WPA_SUPPLICANT_CONF + " -D " + profile['wpa_driver'] + " -P " + WPA_SUPPLICANT_PIDFILE
		wpa_options.extend( wpa_args.split() )
		wpa_options.append( INTERFACE )
		if __debug__:
			print "WPA args: %s" % ( wpa_options, )
		if status_win:
			status_win.update_message("wpa supplicant")
		wpa_pid = os.spawnvp(os.P_NOWAIT,WPA_SUPPLICANT_COMMAND, wpa_options)

	use_dhcp = profile['use_dhcp']
	if use_dhcp :
		dhcp_options = list()
		dhcp_options.append(DHCP_COMMAND)
		dhcp_options.extend(DHCP_ARGS.split())
		dhcp_options.append(INTERFACE)
		if __debug__:
			print "DHCP args: %s" % ( dhcp_options, )
		if status_win:
			status_win.update_message("Acquiring IP Address")
		dhcp_pid = os.spawnvp(os.P_NOWAIT,DHCP_COMMAND, dhcp_options)
		timer = DHCP_TIMEOUT
		tick = 0.25
		while os.waitpid(dhcp_pid,os.WNOHANG) == (0,0):
			if timer < 0:
				os.kill( dhcp_pid, signal.SIGTERM)
				break
			if sys.modules.has_key("gtk"):
				while gtk.events_pending():
					gtk.main_iteration(False)
			timer -= tick
			time.sleep(tick)
 		if not get_current_ip():
 			if status_win:
 				status_win.update_message("Could not get IP address!")
 				if sys.modules.has_key("gtk"):
 					while gtk.events_pending():
 						gtk.main_iteration(False)
 				time.sleep(3)
 			else:
 				print "Could not get IP address!"
 			return
 		else:
 			if status_win:
 				status_win.update_message("Got IP address. Done")
 				if sys.modules.has_key("gtk"):
 					while gtk.events_pending():
 						gtk.main_iteration(False)
 				time.sleep(2)
	else:
		ip 		= profile['ip']
		netmask = profile['netmask']
		gateway = profile['gateway']
		domain	= profile['domain']
		dns1	= profile['dns1']
		dns2 	= profile['dns2']
		ifconfig_command= "%s %s down; %s %s %s netmask %s" % \
			( IFCONFIG_COMMAND, INTERFACE, IFCONFIG_COMMAND, INTERFACE, ip, netmask )
		route_command 	= "%s add default gw %s" % ( ROUTE_COMMAND, gateway )
		s = ''
		if domain != '':
			s += "domain %s\n" % domain
		if dns1 != '':
			s += "nameserver %s\n" % dns1
		if dns2 != '':
			s += "nameserver %s\n" % dns2
		if ( s != '' ):
			f=open('/etc/resolv.conf', 'w')
			f.write(s)
			f.close

		os.system( ifconfig_command )
		os.system( route_command )

	# Let's run the postscript
	postscript = profile['postscript']
	if postscript.strip() != '':
		# got something to execute
		if __debug__:
			print "executing postscript:", postscript
		os.system( postscript )

def	disconnect_interface():
	msg = "Disconnecting"
	say( msg )
	if __debug__:
		print msg
	# Kill off any existing DHCP clients running
	try:
		if DHCP_KILL_COMMAND != '':
			if __debug__:
				print DHCP_KILL_COMMAND
			os.popen( DHCP_KILL_COMMAND )
	except:
		if os.access( DHCP_PIDFILE, os.R_OK):
			if __debug__:
				print "Killing existing DHCP..."
			try:
				os.kill( int(open(DHCP_PIDFILE, mode='r').readline()), signal.SIGTERM )
			except OSError:
				print "Stale pid file.  Removing"
				os.remove( DHCP_PIDFILE )
			if os.path.isfile( DHCP_PIDFILE ):
				print "Stale pid file.  Removing"
				os.remove( DHCP_PIDFILE )
	# Kill off any existing WPA_SUPPLICANT clients running
	if os.access( WPA_SUPPLICANT_PIDFILE, os.R_OK):
		if __debug__:
			print "Killing existing WPA_SUPPLICANT..."
		try:
			if not WPA_SUPPLICANT_KILL_COMMAND == '':
				os.spawnlp( os.P_WAIT, WPA_SUPPLICANT_KILL_COMMAND, WPA_SUPPLICANT_KILL_COMMAND )
			os.kill( int(open(WPA_SUPPLICANT_PIDFILE, mode='r').readline()), signal.SIGTERM )
		except OSError:
			print "Stale pid file.  Removing"
			os.remove( WPA_SUPPLICANT_PIDFILE )
		if os.path.isfile( WPA_SUPPLICANT_PIDFILE ):
			print "Stale pid file.  Removing"
			os.remove( WPA_SUPPLICANT_PIDFILE )
	# Lets clear out the wireless stuff
	if __debug__:
		print 'Lets clear out the wireless stuff'
	os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'essid', 'off' )
	os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'key', 'off' )
	os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'mode', 'auto' )
	os.spawnlp( os.P_WAIT, 'iwconfig', IWCONFIG_COMMAND, INTERFACE, 'channel', 'auto' )
	# Now take the interface down
	if __debug__:
		print 'Now take the interface down'
	os.spawnlp( os.P_WAIT, 'ifconfig', IFCONFIG_COMMAND, INTERFACE, 'down' )
	# Since it may be brought back up by the next scan, let's unset it's IP
	if __debug__:
		print 'Since it may be brought back up by the next scan, lets unset its IP'
	os.spawnlp( os.P_WAIT, 'ifconfig', IFCONFIG_COMMAND, INTERFACE, '0.0.0.0' )
	if __debug__:
		print 'Disconnect complete.'

def get_profile_from_conf_file( essid ):
	global config_options
	# We got the essid, get the key
	profile = {}
	if not confFile.has_section( essid ):
		return None
	profile['ssid']		= essid
	profile['key']		= ''
	profile['mode']		= ''
	profile['security']	= ''
	profile['prescript']= ''
	profile['postscript']= ''
	profile['channel']	= ''
	profile['signal']	= '0'
	profile['protocol']	= 'b'
	if confFile.has_option( essid, "key" ):
		profile['key']	= confFile.get( essid, "key" )
	if confFile.has_option( essid, "mode" ):
		profile['mode']	= confFile.get( essid, "mode" )
	if confFile.has_option( essid, "security" ):
		profile['security']	= confFile.get( essid, "security" )
	if confFile.has_option( essid, "prescript" ):
		profile['prescript']= confFile.get( essid, "prescript" )
	if confFile.has_option( essid, "postscript" ):
		profile['postscript']= confFile.get( essid, "postscript" )
	if confFile.has_option( essid, "channel" ):
		profile['channel']	= confFile.get( essid, "channel" )
	# Now normal network
	profile['use_wpa']	= False
	if confFile.has_option( essid, "use_wpa" ):
		profile['use_wpa'] = confFile.getboolean( essid, "use_wpa" )
	profile['wpa_driver'] 		= ''
	if confFile.has_option( essid, "wpa_driver" ):
		profile['wpa_driver']	= confFile.get( essid, "wpa_driver" )
	profile['use_dhcp']	= False
	if confFile.has_option( essid, "use_dhcp" ):
		profile['use_dhcp'] = confFile.getboolean( essid, "use_dhcp" )
	profile['ip'] 		= ''
	if confFile.has_option( essid, "ip" ):
		profile['ip']	= confFile.get( essid, "ip" )
	profile['netmask']	= ''
	if confFile.has_option( essid, "netmask" ):
		profile['netmask'] = confFile.get( essid, "netmask" )
	profile['gateway']	= ''
	if confFile.has_option( essid, "gateway" ):
		profile['gateway'] = confFile.get( essid, "gateway" )
	profile['domain']	= ''
	if confFile.has_option( essid, "domain" ):
		profile['domain'] = confFile.get( essid, "domain" )
	profile['dns1']		= ''
	if confFile.has_option( essid, "dns1" ):
		profile['dns1'] = confFile.get( essid, "dns1" )
	profile['dns2']		= ''
	if confFile.has_option( essid, "dns2" ):
		profile['dns2'] = confFile.get( essid, "dns2" )
	return profile

def set_profile_to_conf_file( profile ):
	if not confFile.has_section( profile['ssid'] ):
		confFile.add_section( profile['ssid'] )
	confFile.set( profile['ssid'], 'key', profile['key'] )
	confFile.set( profile['ssid'], 'security', profile['security'] )
	confFile.set( profile['ssid'], 'prescript', profile['prescript'] )
	confFile.set( profile['ssid'], 'postscript', profile['postscript'] )
	confFile.set( profile['ssid'], 'mode', profile['mode'] )
	confFile.set( profile['ssid'], 'channel', profile['channel'] )
	# wpa
	if profile['use_wpa']:
		confFile.set( profile['ssid'], 'use_wpa', 'yes' )
		confFile.set( profile['ssid'], 'wpa_driver', profile['wpa_driver'] )
	else:
		confFile.set( profile['ssid'], 'use_wpa', 'no' )
	# dhcp
	if profile['use_dhcp']:
		confFile.set( profile['ssid'], 'use_dhcp', 'yes' )
		try: confFile.remove_option( profile['ssid'], 'ip' )
		except: pass
		try: confFile.remove_option( profile['ssid'], 'netmask' )
		except: pass
		try: confFile.remove_option( profile['ssid'], 'gateway' )
		except: pass
		try: confFile.remove_option( profile['ssid'], 'domain' )
		except: pass
		try: confFile.remove_option( profile['ssid'], 'dns1' )
		except: pass
		try: confFile.remove_option( profile['ssid'], 'dns2' )
		except: pass
	else:
		confFile.set( profile['ssid'], 'use_dhcp', 'no' )
		confFile.set( profile['ssid'], 'ip', profile['ip'] )
		confFile.set( profile['ssid'], 'netmask', profile['netmask'] )
		confFile.set( profile['ssid'], 'gateway', profile['gateway'] )
		confFile.set( profile['ssid'], 'domain', profile['domain'] )
		confFile.set( profile['ssid'], 'dns1', profile['dns1'] )
		confFile.set( profile['ssid'], 'dns2', profile['dns2'] )
	confFile.write( open( CONF_FILE, "w" ) )

##################
# The main window
class radar_window:
	def __init__( self ):
		# create the main window and connect the normal events
		global	signal_xpm_none
		global	signal_xpm_low
		global	signal_xpm_barely
		global	signal_xpm_ok
		global	signal_xpm_best
		global	known_profile_icon
		global	unknown_profile_icon
		global	wifi_radar_icon
		self.signal_none_pb	= gtk.gdk.pixbuf_new_from_xpm_data( signal_xpm_none )
		self.known_profile_icon		= gtk.gdk.pixbuf_new_from_inline( len( known_profile_icon[0] ), known_profile_icon[0], False )
		self.unknown_profile_icon	= gtk.gdk.pixbuf_new_from_inline( len( unknown_profile_icon[0] ), unknown_profile_icon[0], False )
		self.signal_low_pb	= gtk.gdk.pixbuf_new_from_xpm_data( signal_xpm_low )
		self.signal_barely_pb= gtk.gdk.pixbuf_new_from_xpm_data( signal_xpm_barely )
		self.signal_ok_pb	= gtk.gdk.pixbuf_new_from_xpm_data( signal_xpm_ok )
		self.signal_best_pb	= gtk.gdk.pixbuf_new_from_xpm_data( signal_xpm_best )
		self.window = gtk.Dialog('WiFi Radar', None, gtk.DIALOG_MODAL )
		icon = gtk.gdk.pixbuf_new_from_inline( len( wifi_radar_icon[0] ), wifi_radar_icon[0], False )
		self.window.set_icon( icon )
		self.window.set_border_width( 10 )
		self.window.set_size_request( 450, 300 )
		self.window.set_title( "WiFi Radar" )
		self.window.connect( 'delete_event', self.delete_event )
		self.window.connect( 'destroy', self.destroy, )
		# let's create all our widgets
		self.current_network = gtk.Label()
		self.current_network.show()
		self.close_button = gtk.Button( "Close", gtk.STOCK_CLOSE )
		self.close_button.show()
		self.close_button.connect( 'clicked', self.delete_event, None  )
		#                            apname known_icon      known available wep_icon signal_level    mode protocol
		self.pstore = gtk.ListStore( str,   gtk.gdk.Pixbuf, int,  int,      str,     gtk.gdk.Pixbuf, str, str )
		self.rebuild_plist_items()
		self.plist = gtk.TreeView( self.pstore )
		self.pcol	= gtk.TreeViewColumn( "SSID" )
		# The ssid column
		self.plist.append_column( self.pcol )
		self.pix_cell 	= gtk.CellRendererPixbuf()
		self.wep_cell 	= gtk.CellRendererPixbuf()
		self.ssid_cell 	= gtk.CellRendererText()
		self.pcol.pack_start( self.pix_cell, False )
		self.pcol.pack_start( self.wep_cell, False )
		self.pcol.pack_start( self.ssid_cell, True )
		self.pcol.add_attribute( self.wep_cell, 'stock-id', 4 )
		self.pcol.add_attribute( self.pix_cell, 'pixbuf', 1 )
		self.pcol.add_attribute( self.ssid_cell, 'text', 0 )
		self.sig_cell 	= gtk.CellRendererPixbuf()
		self.scol	= gtk.TreeViewColumn( "Signal" )
		self.scol.pack_start( self.sig_cell, True )
		self.scol.add_attribute( self.sig_cell, 'pixbuf', 5 )
		self.plist.append_column( self.scol )
		# The mode column
		self.mode_cell 	= gtk.CellRendererText()
		self.mcol	= gtk.TreeViewColumn( "Mode" )
		self.mcol.pack_start( self.mode_cell, True )
		self.mcol.add_attribute( self.mode_cell, 'text', 6 )
		self.plist.append_column( self.mcol )
		# The protocol column
		self.prot_cell 	= gtk.CellRendererText()
		self.protcol	= gtk.TreeViewColumn( "802.11" )
		self.protcol.pack_start( self.prot_cell, True )
		self.protcol.add_attribute( self.prot_cell, 'text', 7 )
		self.plist.append_column( self.protcol )
		# DnD Ordering
		self.plist.set_reorderable( True )
		self.pstore.connect( 'row-changed', self.save_auto_profile_order )
		# the list scroll bar
		sb = gtk.VScrollbar( self.plist.get_vadjustment() )
		sb.show()
		self.plist.show()
		#
		self.new_button = gtk.Button( "New" )
		self.new_button.connect( 'clicked', self.create_new_profile, None  )
		self.new_button.show()
		#
		self.edit_button = gtk.Button( "Edit" )
		self.edit_button.connect( 'clicked', self.edit_profile, None  )
		self.edit_button.show()
		#
		self.delete_button = gtk.Button( "Delete" )
		self.delete_button.connect( 'clicked', self.delete_profile, None  )
		self.delete_button.show()
		#
		self.connect_button = gtk.Button( "Connect" )
		self.connect_button.connect( 'clicked', self.connect_profile, None  )
		#
		self.disconnect_button = gtk.Button( "Disconnect" )
		self.disconnect_button.connect( 'clicked', self.disconnect_profile, None  )
		# lets add our widgets
		rows		= gtk.VBox( False, 3 )
		listcols	= gtk.HBox( False, 0 )
		prows		= gtk.VBox( False, 0 )
		# lets start packing
		# the rows level
		rows.pack_start( listcols, True, True, 0 )
		rows.pack_start( self.current_network, False, True, 0 )
		# the list columns
		listcols.pack_start( self.plist, True, True, 0 )
		listcols.pack_start( sb, False, False, 0 )
		listcols.pack_start( prows, False, False, 5 )
		# the list buttons
		prows.pack_start( self.new_button, False, False, 2 )
		prows.pack_start( self.edit_button, False, False, 2 )
		prows.pack_start( self.delete_button, False, False, 2 )
		prows.pack_end( self.connect_button, False, False, 2 )
		prows.pack_end( self.disconnect_button, False, False, 2 )
		#self.window.action_area.set_homogeneous( True )
		#self.window.action_area.pack_start( self.current_network )
		self.window.action_area.pack_start( self.close_button )
		rows.show()
		listcols.show()
		prows.show()
		self.window.vbox.add( rows )
		self.window.vbox.set_spacing( 3 )
		self.window.show_all()
		#
		# Now, immediately hide these two.  The proper one will be
		# displayed later, based on interface state. -BEF-
		self.disconnect_button.hide()
		self.connect_button.hide()

	def main( self ):
		gtk.main()

	def destroy( self, widget = None):
		global lock
		if not lock.locked():
			lock.acquire()
		gtk.main_quit()
		try: lock.release()
		except: pass

	def delete_event( self, widget, event, data=None ):
		# Save the preferred networks order
		global exit_flag
		exit_flag = True
		self.save_auto_profile_order()
		self.destroy()
		return False

	def rebuild_plist_items( self ):
		# Add our known profiles in order
		global lock
		try: 	lock.acquire()
		except:	pass
		for ssid in auto_profile_order:
			ssid = ssid.strip()
			if access_points.has_key( ssid ) and access_points[ ssid ]['known']:
				wep = None
				if access_points[ ssid ]['encrypted']: wep = gtk.STOCK_DIALOG_AUTHENTICATION
				# 1 here means that we know this ssid ---------------v
				self.pstore.append( [ ssid, self.known_profile_icon, 1, 0, wep, self.signal_none_pb, access_points[ ssid ]['mode'], access_points[ ssid ]['protocol'] ] )
		# Now add any known profiles not in the profile order
		for ap in access_points:
			if ap in auto_profile_order: continue
			wep = None
			if access_points[ ap ]['encrypted']: wep = gtk.STOCK_DIALOG_AUTHENTICATION
			# 1 here means that we know this ssid ---------------v
			self.pstore.append( [ ap, self.unknown_profile_icon, 0, 0, wep, self.signal_none_pb, access_points[ ap ]['mode'], access_points[ ap ]['protocol'] ] )
		try:	lock.release()
		except: pass

	def update_plist_items( self ):
		"""Updates the profiles list"""
		global lock
		global current_ip
		global current_ssid
		#if __debug__:
		#	print "updating profile list"
		gtk.threads_enter()
		if not lock.locked():
			lock.acquire()
		# update the current ip and ssid
		self.current_network.set_text( "Connected to %s ip(%s)" % ( current_ssid, current_ip ) )
		if current_ip == 'None':
			self.disconnect_button.hide()
			self.connect_button.show()
		else:
			self.connect_button.hide()
			self.disconnect_button.show()

		for ap in access_points:
			wep = None
			if access_points[ ap ]['encrypted']: wep = gtk.STOCK_DIALOG_AUTHENTICATION
			prow = self.get_row_by_ssid( ap )
			if prow:
				#if __debug__:
				#	print "Setting prow", ap, access_points[ ap ]
				prow[4] = wep
				prow[5] = self.pixbuf_from_signal( access_points[ ap ][ 'signal' ] )
				prow[6] = access_points[ ap ][ 'mode' ]
				prow[7] = access_points[ ap ][ 'protocol' ]
				#for val in prow:
				#	print val
			else:
				#if __debug__:
				#	print "New profile", ap, access_points[ ap ]
				# 1 here means that we know this ssid ---------------v
				self.pstore.append( [ ap, self.unknown_profile_icon, 0, 0, wep,
					self.pixbuf_from_signal( access_points[ ap ]['signal'] ),
					access_points[ ap ]['mode'],
					access_points[ ap ]['protocol'] ] )
			# give the list a chance to update
			#while gtk.events_pending():
			#	gtk.main_iteration()
		try: lock.release()
		except: pass
		gtk.threads_leave()
		return True

	def pixbuf_from_signal( self, signal ):
		signal = int( signal )
		#print signal
		if signal >= 80 or signal == 0:
			return self.signal_none_pb
		elif signal >= 78:
			return self.signal_low_pb
		elif signal >= 75:
			return self.signal_barely_pb
		elif signal >= 60:
			return self.signal_ok_pb
		elif signal < 60:
			return self.signal_best_pb
		else:
			return None

	def get_row_by_ssid( self, ssid ):
		for row in self.pstore:
			if row[0] == ssid:
				#print row
				return row
		return None

	def create_new_profile( self, widget, data=None ):
		global lock
		p = profile_dialog( self )
		while True:
			ok = p.run()
			if ok:
				profile = p.get_profile()
				# Check that the ssid does not exist already
				if profile['ssid'] in access_points:
					dlg = gtk.MessageDialog(
						self.window,
						gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
						gtk.MESSAGE_ERROR,
						gtk.BUTTONS_OK,
						"A profile for %s already exists" % profile['ssid'] )
					dlg.run()
					dlg.destroy()
					del dlg
					# try again
					continue
				set_profile_to_conf_file( profile )
				# Add lets add it up
				ap = {}
				ap['known']		= True
				ap['available']	= False
				ap['encrypted'] = False
				ap['mode']		= ''
				ap['security']	= ''
				ap['prescript']	= ''
				ap['postscript']= ''
				ap['channel']	= ''
				ap['protocol']	= 'b'
				ap['signal']	= '0'
				if confFile.has_option( profile['ssid'], 'key'):
					if len( confFile.get( profile['ssid'], 'key' ) ) > 0:
						ap['encrypted'] = True
				lock.acquire()
				access_points[ profile['ssid'] ] = ap
				# if it is not in the auto_profile_order add it
				if not profile['ssid'] in auto_profile_order:
					auto_profile_order.append( profile['ssid'] )
				lock.release()
				# add to the store
				wep = None
				if ap['encrypted']: wep = gtk.STOCK_DIALOG_AUTHENTICATION
				self.pstore.append( [ profile['ssid'], self.known_profile_icon, 1, 0, wep, self.pixbuf_from_signal( ap['signal'] ), ap['mode'], ap['protocol'] ] )
			break
		p.destroy()

	def edit_profile( self, widget, data=None ):
		( store, selected_iter ) = self.plist.get_selection().get_selected()
		if not selected_iter: return
		ssid	= store.get_value( selected_iter, 0 )
		known	= store.get_value( selected_iter, 2 )
		if not known: return
		profile = get_profile_from_conf_file( ssid )
		p = profile_dialog( self )
		p.set_profile( profile, True )
		ok = p.run()
		if ok:
			profile = p.get_profile()
			if __debug__:
				print "Got edited profile ", profile
			set_profile_to_conf_file( profile )
		p.destroy()

	def delete_profile( self, widget, data=None ):
		( store, selected_iter ) = self.plist.get_selection().get_selected()
		if not selected_iter: return
		ssid	= store.get_value( selected_iter, 0 )
		known	= store.get_value( selected_iter, 2 )
		if not known: return
		dlg = gtk.MessageDialog(
					self.window,
					gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
					gtk.MESSAGE_QUESTION,
					gtk.BUTTONS_YES_NO,
				"Are you sure you want to delete the %s profile?" % ssid )
		res = dlg.run()
		dlg.destroy()
		del dlg
		if res == gtk.RESPONSE_NO: return
		# Remove it
		confFile.remove_section( ssid )
		if ssid in auto_profile_order: auto_profile_order.remove( ssid )
		if access_points.has_key( ssid ): access_points.pop( ssid )
		self.pstore.remove( selected_iter )
		# Let's save our current state
		self.save_auto_profile_order()

	def connect_profile( self, widget, data=None ):
		( store, selected_iter ) = self.plist.get_selection().get_selected()
		if not selected_iter: return
		ssid	= store.get_value( selected_iter, 0 )
		known	= store.get_value( selected_iter, 2 )
		if not known:
			dlg = gtk.MessageDialog(
					self.window,
					gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
					gtk.MESSAGE_QUESTION,
					gtk.BUTTONS_YES_NO,
				"This network does not have a profile configured.\n\nWould you like to create one now?" )
			res = dlg.run()
			dlg.destroy()
			del dlg
			if res == gtk.RESPONSE_NO: return
			p = profile_dialog( self )
			# get a blank profile from the dialog
			profile = p.get_profile()
			profile['ssid'] = ssid
			p.set_profile( profile, True )
			ok = p.run()
			if ok:
				profile = p.get_profile()
				set_profile_to_conf_file( profile )
				# change the icon
				self.pstore.set_value( selected_iter, 1, self.known_profile_icon )
				# make it known
				self.pstore.set_value( selected_iter, 2, 1 )
				# if it is not in the auto_profile_order add it
				if not profile['ssid'] in auto_profile_order:
					auto_profile_order.append( profile['ssid'] )
				self.save_auto_profile_order()
				p.destroy()
				connect_status_window = status_window()
				connect_status_window.run()
				connect_to_network( ssid, connect_status_window )
				connect_status_window.destroy()
			else:
				p.destroy()
		else:
			connect_status_window = status_window()
			connect_status_window.run()
			connect_to_network( ssid, connect_status_window )
			connect_status_window.destroy()

	def disconnect_profile( self, widget, data=None ):
		disconnect_interface()

	def get_ssid_iter( self, ssid ):
		piter = self.pstore.get_iter_first()
		while piter:
			# only if it's known
			if self.pstore.get_value( piter, 0 ) == ssid: break
		return piter

	def save_auto_profile_order( self, widget = None, data = None, data2 = None ):
		# recreate the auto_profile_order
		auto_profile_order = []
		piter = self.pstore.get_iter_first()
		while piter:
			# only if it's known
			if self.pstore.get_value( piter, 2 ) == 1:
				auto_profile_order.append( self.pstore.get_value( piter, 0 ) )
			piter = self.pstore.iter_next( piter )
		# save it
		apo = ','.join( auto_profile_order )
		confFile.set( 'DEFAULT', 'auto_profile_order', apo )
		confFile.write( open( CONF_FILE, 'w' ) )

###################################
class profile_dialog:
	def __init__( self, parent ):
		global wifi_radar_icon
		self.parent = parent
		self.dialog = gtk.Dialog('WiFi Profile', self.parent.window,
								gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
								( gtk.STOCK_CANCEL, False, gtk.STOCK_SAVE, True ) )
		icon = gtk.gdk.pixbuf_new_from_inline( len( wifi_radar_icon[0] ), wifi_radar_icon[0], False )
		self.dialog.set_icon( icon )
		self.dialog.set_resizable( False )
		self.dialog.set_transient_for( self.parent.window )
		#self.dialog.set_size_request( 400, 400 )
		ssid_table = gtk.Table( 1, 2, False )
		ssid_table.set_row_spacings( 3 )
		ssid_table.set_col_spacings( 3 )
		#################
		# The ssid labels
		l = gtk.Label( 'Network Name' )
		ssid_table.attach( l, 0, 1, 0, 1 )
		# The ssid textboxes
		self.ssid = gtk.Entry( 32 )
		self.ssid.set_text('ssid')
		ssid_table.attach( self.ssid, 1, 2, 0, 1 )
		#self.key = gtk.Entry( 32 )
		#ssid_table.attach( self.key, 1, 2, 1, 2 )
		# Add the ssid table to the dialog
		self.dialog.vbox.pack_start( ssid_table, True, True, 5 )


		# create the wifi expander
		self.wifi_expander = gtk.Expander( WIFI_SET_LABEL )
		#self.wifi_expander.connect( 'notify::expanded', self.toggle_use_dhcp )
		wifi_table = gtk.Table( 4, 2, False )
		wifi_table.set_row_spacings( 3 )
		wifi_table.set_col_spacings( 3 )
		# The Wifi labels
		l = gtk.Label( 'Mode' )
		wifi_table.attach( l, 0, 1, 0, 1 )
		l = gtk.Label( 'Channel' )
		wifi_table.attach( l, 0, 1, 1, 2 )
		l = gtk.Label( 'Key' )
		wifi_table.attach( l, 0, 1, 2, 3 )
		l = gtk.Label( 'Security' )
		wifi_table.attach( l, 0, 1, 3, 4 )
		# The Wifi text boxes
		self.mode = gtk.combo_box_new_text()
		for mode in WIFI_MODES:
			self.mode.append_text( mode )
		self.mode.set_active( 0 )
		wifi_table.attach( self.mode, 1, 2, 0, 1 )
		self.channel = gtk.combo_box_new_text()
		for channel in WIFI_CHANNELS:
			self.channel.append_text( channel )
		self.channel.set_active( 0 )
		wifi_table.attach( self.channel, 1, 2, 1, 2 )
		self.key = gtk.Entry( 32 )
		#self.key.set_text('0.0.0.0')
		wifi_table.attach( self.key, 1, 2, 2, 3 )
		self.security = gtk.combo_box_new_text()
		for security in WIFI_SECURITY:
			self.security.append_text( security )
		self.security.set_active( 0 )
		wifi_table.attach( self.security, 1, 2, 3, 4 )
		# Add the wifi table to the expander
		self.wifi_expander.add( wifi_table )
		# Add the expander to the dialog
		self.dialog.vbox.pack_start( self.wifi_expander, False, False, 5 )

		# create the wpa expander
		self.wpa_expander = gtk.Expander( NO_WPA_LABEL )
		self.wpa_expander.connect( 'notify::expanded', self.toggle_use_wpa )
		wpa_table = gtk.Table( 1, 2, False )
		wpa_table.set_row_spacings( 3 )
		wpa_table.set_col_spacings( 3 )
		# The labels
		l = gtk.Label( 'Driver' )
		wpa_table.attach( l, 0, 1, 0, 1 )
		# The text boxes
		self.wpa_driver = gtk.Entry()
		wpa_table.attach( self.wpa_driver, 1, 2, 0, 1 )
		# Add the wpa table to the expander
		self.wpa_expander.add( wpa_table )
		# Add the expander to the dialog
		self.dialog.vbox.pack_start( self.wpa_expander, False, False, 5 )

		# create the dhcp expander
		self.dhcp_expander = gtk.Expander( USE_DHCP_LABEL )
		self.dhcp_expander.connect( 'notify::expanded', self.toggle_use_dhcp )
		ip_table = gtk.Table( 6, 2, False )
		ip_table.set_row_spacings( 3 )
		ip_table.set_col_spacings( 3 )
		# The IP labels
		l = gtk.Label( 'IP' )
		ip_table.attach( l, 0, 1, 0, 1 )
		l = gtk.Label( 'Netmask' )
		ip_table.attach( l, 0, 1, 1, 2 )
		l = gtk.Label( 'Gateway' )
		ip_table.attach( l, 0, 1, 2, 3 )
		l = gtk.Label( 'Domain' )
		ip_table.attach( l, 0, 1, 3, 4 )
		l = gtk.Label( 'DNS' )
		ip_table.attach( l, 0, 1, 4, 5 )
		l = gtk.Label( 'DNS' )
		ip_table.attach( l, 0, 1, 5, 6 )
		# The IP text boxes
		self.ip = gtk.Entry( 15 )
		self.ip.set_text('0.0.0.0')
		ip_table.attach( self.ip, 1, 2, 0, 1 )
		self.netmask = gtk.Entry( 15 )
		self.netmask.set_text('255.255.255.0')
		ip_table.attach( self.netmask, 1, 2, 1, 2 )
		self.gw = gtk.Entry( 15 )
		self.gw.set_text('0.0.0.0')
		ip_table.attach( self.gw, 1, 2, 2, 3 )
		self.domain = gtk.Entry( 32 )
		self.domain.set_text('domain.com')
		ip_table.attach( self.domain, 1, 2, 3, 4 )
		self.dns1 = gtk.Entry( 15 )
		self.dns1.set_text('0.0.0.0')
		ip_table.attach( self.dns1, 1, 2, 4, 5 )
		self.dns2 = gtk.Entry( 15 )
		self.dns2.set_text('0.0.0.0')
		ip_table.attach( self.dns2, 1, 2, 5, 6 )
		# Add the ip table to the expander
		self.dhcp_expander.add( ip_table )
		# Add the expander to the dialog
		self.dialog.vbox.pack_start( self.dhcp_expander, False, False, 5 )

		# create the postpre expander
		self.postpre_expander = gtk.Expander( POSTPRE_LABEL )
		pp_table = gtk.Table( 2, 2, False )
		pp_table.set_row_spacings( 3 )
		pp_table.set_col_spacings( 3 )
		# The labels
		l = gtk.Label( 'Before' )
		pp_table.attach( l, 0, 1, 0, 1 )
		l = gtk.Label( 'After' )
		pp_table.attach( l, 0, 1, 1, 2 )
		# The text boxes
		self.prescript = gtk.Entry()
		pp_table.attach( self.prescript, 1, 2, 0, 1 )
		self.postscript = gtk.Entry()
		pp_table.attach( self.postscript, 1, 2, 1, 2 )
		# Add the pp table to the expander
		self.postpre_expander.add( pp_table )
		# Add the expander to the dialog
		self.dialog.vbox.pack_start( self.postpre_expander, False, False, 5 )

	def run( self ):
		self.dialog.show_all()
		return self.dialog.run()

	def destroy( self ):
		self.dialog.destroy()
		del self.dialog

	def toggle_use_dhcp( self, widget, data = None ):
		expanded = self.dhcp_expander.get_expanded()
		if expanded:
			self.dhcp_expander.set_label( USE_IP_LABEL )
		else:
			self.dhcp_expander.set_label( USE_DHCP_LABEL )

	def toggle_use_wpa( self, widget, data = None ):
		expanded = self.wpa_expander.get_expanded()
		if expanded:
			self.wpa_expander.set_label( USE_WPA_LABEL )
		else:
			self.wpa_expander.set_label( NO_WPA_LABEL )

	def get_profile( self ):
		profile					= {}
		profile['ssid']			= self.ssid.get_text().strip()
		profile['key']			= self.key.get_text().strip()
		profile['mode']			= self.get_array_item( self.mode.get_active(), WIFI_MODES )
		profile['security']		= self.get_array_item( self.security.get_active(), WIFI_SECURITY )
		profile['channel']		= self.get_array_item( self.channel.get_active(), WIFI_CHANNELS )
		profile['protocol']		= 'b'
		profile['signal']		= '0'
		profile['prescript']	= self.prescript.get_text().strip()
		profile['postscript']	= self.postscript.get_text().strip()
		# wpa
		use_wpa 				= ( self.wpa_expander.get_expanded() == False )
		if use_wpa:
			profile['use_wpa'] = False
		else:
			profile['use_wpa'] = True
			profile['wpa_driver']= self.wpa_driver.get_text().strip()
		# dhcp
		use_dhcp 				= ( self.dhcp_expander.get_expanded() == False )
		if use_dhcp:
			profile['use_dhcp'] = True
		else:
			profile['use_dhcp'] = False
			profile['ip']		= self.ip.get_text().strip()
			profile['netmask']	= self.netmask.get_text().strip()
			profile['gateway']	= self.gw.get_text().strip()
			profile['domain']	= self.domain.get_text().strip()
			profile['dns1']		= self.dns1.get_text().strip()
			profile['dns2']		= self.dns2.get_text().strip()
		return profile

	def set_profile( self, profile, known ):
		if __debug__:
			print profile
		self.ssid.set_text( profile['ssid'] )
		if known:
			self.ssid.set_editable( False )
			self.dialog.set_title( "WiFi Profile for %s" % profile['ssid'] )
		self.key.set_text( profile['key'] )
		self.mode.set_active( self.get_array_index( profile['mode'], WIFI_MODES ) )
		self.channel.set_active( self.get_array_index( profile['channel'], WIFI_CHANNELS ) )
		self.security.set_active( self.get_array_index( profile['security'], WIFI_SECURITY ) )
		#self.protocol.set_text( profile['protocol'] )
		self.prescript.set_text( profile['prescript'] )
		self.postscript.set_text( profile['postscript'] )
		# wpa
		if profile['use_wpa'] == True:
			self.wpa_expander.set_expanded( True )
			self.wpa_driver.set_text( profile['wpa_driver'] )
		else:
			self.wpa_expander.set_expanded( False )
		# dhcp
		if profile['use_dhcp'] == True:
			self.dhcp_expander.set_expanded( False)
		else:
			self.dhcp_expander.set_expanded( True )
			self.ip.set_text( profile['ip'] )
			self.netmask.set_text( profile['netmask']	)
			self.gw.set_text( profile['gateway'] )
			self.domain.set_text( profile['domain'] )
			self.dns1.set_text( profile['dns1'] )
			self.dns2.set_text( profile['dns2'] )

	def get_array_index( self, item, array ):
		try:
			return array.index( item.strip() )
		except:
			pass
		return 0

	def get_array_item( self, index, array ):
		try:
			return array[ index ]
		except:
			pass
		return ''

### status_window
###
### A simple class for putting up a "Please wait" dialog so the user
### doesn't think we've forgotten about them.
class status_window:
	def __init__( self ):
		global wifi_radar_icon
		self.dialog = gtk.Dialog(title="Working", flags=gtk.DIALOG_MODAL)
		icon = gtk.gdk.pixbuf_new_from_inline( len( wifi_radar_icon[0] ), wifi_radar_icon[0], False )
		self.dialog.set_icon( icon )
		self.lbl = gtk.Label("Please wait...")
		self.bar = gtk.ProgressBar()
		self.dialog.vbox.pack_start(self.lbl)
		self.dialog.vbox.pack_start(self.bar)
		self.dialog.show_all()
		self.dialog.connect("delete_event",self.inhibit_close)

	def update_message( self, message ):
		self.lbl.set_text(message)

	def inhibit_close( self, widget, signal ):
		return True

	def update_window( self ):
		# Do stuff
		self.bar.pulse()
		return True

	def run( self ):
		self.dialog.show_all()
		self.timer = gobject.timeout_add(250,self.update_window)
		return

	def destroy( self ):
		gobject.source_remove(self.timer)
		self.dialog.destroy()
		del self.dialog


####################################################################################################
# Speaking up
def	say( words ):
	if not SPEAK_UP: return
	words = words.replace( "\"", "\\\"" )
	os.system( "%s \"%s\"" % ( SAY_COMMAND, words ) )
	#os.spawnlp( os.P_WAIT, SAY_COMMAND, SAY_COMMAND, words )

# Configure
def configure():
	global main_radar_window
	global scanner
	global lock
	main_radar_window = radar_window()
	lock = thread.allocate_lock()
	thread.start_new( scanning_thread, ( lock, ) )
	gobject.timeout_add( 500, main_radar_window.update_plist_items )
	main_radar_window.main()


####################################################################################################
# Initializers
access_points		= {}
auto_profile_order	= []
lock				= None
s					= None
#sys.setcheckinterval( 100 )
# First load our conf file and know profiles
confFile			= ConfigParser.ConfigParser()
if not os.path.isfile( CONF_FILE ):
	# No config file exists, build one real quick
	confFile.set("DEFAULT", "interface", INTERFACE )
	confFile.set("DEFAULT", "scan_timeout", SCAN_TIMEOUT )
	confFile.set("DEFAULT", "speak_up", SPEAK_UP )
	confFile.set("DEFAULT", "commit_required", COMMIT_REQUIRED )
	confFile.set("DEFAULT", "ifup_required", IFUP_REQUIRED )
	confFile.set("DEFAULT", "auto_profile_order", '' )
	confFile.write( open( CONF_FILE, "w" ) )
else:
	confFile.readfp( open( CONF_FILE ) )
	# Override the defaults
	try: INTERFACE		= confFile.get			( "DEFAULT", "interface" )
	except: confFile.set("DEFAULT", "interface", INTERFACE )
	try: SCAN_TIMEOUT	= confFile.getint		( "DEFAULT", "scan_timeout" )
	except: confFile.set("DEFAULT", "scan_timeout", SCAN_TIMEOUT )
	try: SPEAK_UP		= confFile.getboolean	( "DEFAULT", "speak_up" )
	except: confFile.set("DEFAULT", "speak_up", SPEAK_UP )
	try: COMMIT_REQUIRED= confFile.getboolean	( "DEFAULT", "commit_required" )
	except: confFile.set("DEFAULT", "commit_required", COMMIT_REQUIRED )
	try: IFUP_REQUIRED= confFile.getboolean	( "DEFAULT", "ifup_required" )
	except: confFile.set("DEFAULT", "ifup_required", IFUP_REQUIRED )
	try: auto_profile_order	= confFile.get	( "DEFAULT", "auto_profile_order" )
	except: confFile.set("DEFAULT", "auto_profile_order", auto_profile_order )
	# convert the auto_profile_order to a list for ordering
	if auto_profile_order == '':
		auto_profile_order = []
	else:
		auto_profile_order = auto_profile_order.split( ',' )
	# First, we add our known profiles
	for apname in confFile.sections():
		ap = {}
		# set the defaults
		ap['known']		= True
		ap['available']	= False
		ap['encrypted'] = False
		ap['mode']		= ''
		ap['security']	= ''
		ap['channel']	= ''
		ap['protocol']	= 'g'
		ap['signal']	= '0'
		ap['prescript']	= ''
		ap['postscript']= ''
		# read the important values
		if confFile.has_option( apname, 'key'):
			if len( confFile.get( apname, 'key' ) ) > 0:
				ap['encrypted'] = True
		if confFile.has_option( apname, 'mode'):
			apmode = confFile.get( apname, 'mode' )
			if len( apmode ) > 0:
				ap['mode'] = apmode
		if confFile.has_option( apname, 'security'):
			apsec = confFile.get( apname, 'security' )
			if len( apsec ) > 0:
				ap['security'] = apsec
		if confFile.has_option( apname, 'channel'):
			apchan = confFile.get( apname, 'channel' )
			if len( apchan ) > 0:
				ap['channel'] = apchan
		if confFile.has_option( apname, 'protocol'):
			approt = confFile.get( apname, 'protocol' )
			if len( approt ) > 0:
				ap['protocol'] = approt
		access_points[ apname ] = ap
		# if it is not in the auto_profile_order add it
		if not apname in auto_profile_order:
			auto_profile_order.append( apname )
####################################################################################################
# Embedded Images
wifi_radar_icon = [ ""
  "GdkP"
  "\0\0\22""7"
  "\2\1\0\2"
  "\0\0\1\214"
  "\0\0\0c"
  "\0\0\0O"
  "\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377"
  "\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\261\377\377"
  "\377\0\7\0\0\0\10\0\0\0\25\0\0\0\35\0\0\0%\0\0\0-\0\0\0\"\0\0\0\11\327"
  "\377\377\377\0\6\0\0\0\"\0\0\0_\0\0\0\213\0\0\0\266\0\0\0\341\0\0\0\376"
  "\206\0\0\0\377\6\0\0\0\356\0\0\0\324\0\0\0\265\0\0\0~\0\0\0@\0\0\0\10"
  "\315\377\377\377\0\4\0\0\0\2\0\0\0;\0\0\0\210\0\0\0\325\221\0\0\0\377"
  "\4\0\0\0\371\0\0\0\303\0\0\0w\0\0\0\31\310\377\377\377\0\3\0\0\0\6\0"
  "\0\0m\0\0\0\342\227\0\0\0\377\4\0\0\0\374\0\0\0\264\0\0\0Q\0\0\0\5\303"
  "\377\377\377\0\3\0\0\0\4\0\0\0d\0\0\0\341\234\0\0\0\377\3\0\0\0\341\0"
  "\0\0`\0\0\0\2\277\377\377\377\0\3\0\0\0\2\0\0\0[\0\0\0\333\240\0\0\0"
  "\377\2\0\0\0\323\0\0\0K\274\377\377\377\0\3\0\0\0\1\0\0\0R\0\0\0\324"
  "\244\0\0\0\377\2\0\0\0\276\0\0\0#\271\377\377\377\0\2\0\0\0\31\0\0\0"
  "\277\247\0\0\0\377\2\0\0\0\363\0\0\0c\267\377\377\377\0\2\0\0\0/\0\0"
  "\0\343\252\0\0\0\377\2\0\0\0\257\0\0\0\24\264\377\377\377\0\2\0\0\0M"
  "\0\0\0\363\220\0\0\0\377\14\0\0\0\357\0\0\0\304\0\0\0\230\0\0\0v\0\0"
  "\0l\0\0\0c\0\0\0[\0\0\0j\0\0\0\205\0\0\0\240\0\0\0\311\0\0\0\373\220"
  "\0\0\0\377\2\0\0\0\346\0\0\0""4\262\377\377\377\0\2\0\0\0q\0\0\0\375"
  "\215\0\0\0\377\4\0\0\0\373\0\0\0\300\0\0\0t\0\0\0)\213\377\377\377\0"
  "\4\0\0\0\14\0\0\0E\0\0\0\205\0\0\0\334\216\0\0\0\377\2\0\0\0\363\0\0"
  "\0D\257\377\377\377\0\2\0\0\0\4\0\0\0\230\215\0\0\0\377\3\0\0\0\372\0"
  "\0\0\231\0\0\0\34\221\377\377\377\0\4\0\0\0\1\0\0\0C\0\0\0\251\0\0\0"
  "\372\214\0\0\0\377\2\0\0\0\371\0\0\0W\255\377\377\377\0\2\0\0\0\17\0"
  "\0\0\272\214\0\0\0\377\3\0\0\0\375\0\0\0\241\0\0\0\"\226\377\377\377"
  "\0\2\0\0\0\"\0\0\0\252\214\0\0\0\377\2\0\0\0\375\0\0\0k\253\377\377\377"
  "\0\2\0\0\0\25\0\0\0\324\213\0\0\0\377\3\0\0\0\376\0\0\0\252\0\0\0(\232"
  "\377\377\377\0\2\0\0\0""9\0\0\0\312\214\0\0\0\377\1\0\0\0\200\251\377"
  "\377\377\0\2\0\0\0\5\0\0\0\303\213\0\0\0\377\2\0\0\0\332\0\0\0""1\235"
  "\377\377\377\0\3\0\0\0\4\0\0\0\201\0\0\0\374\213\0\0\0\377\1\0\0\0p\250"
  "\377\377\377\0\1\0\0\0\222\213\0\0\0\377\2\0\0\0\301\0\0\0\22\240\377"
  "\377\377\0\2\0\0\0:\0\0\0\336\212\0\0\0\377\2\0\0\0\374\0\0\0I\246\377"
  "\377\377\0\1\0\0\0[\213\0\0\0\377\2\0\0\0\241\0\0\0\6\212\377\377\377"
  "\0\15\0\0\0\2\0\0\0&\0\0\0U\0\0\0\203\0\0\0\242\0\0\0\243\0\0\0\234\0"
  "\0\0\225\0\0\0\215\0\0\0\206\0\0\0}\0\0\0\\\0\0\0!\213\377\377\377\0"
  "\2\0\0\0\22\0\0\0\307\212\0\0\0\377\2\0\0\0\361\0\0\0+\244\377\377\377"
  "\0\2\0\0\0.\0\0\0\365\211\0\0\0\377\2\0\0\0\376\0\0\0|\211\377\377\377"
  "\0\4\0\0\0#\0\0\0d\0\0\0\223\0\0\0\277\214\0\0\0\310\4\0\0\0\253\0\0"
  "\0l\0\0\0-\0\0\0\2\210\377\377\377\0\2\0\0\0\12\0\0\0\267\212\0\0\0\377"
  "\2\0\0\0\336\0\0\0\24\242\377\377\377\0\2\0\0\0\20\0\0\0\334\211\0\0"
  "\0\377\2\0\0\0\367\0\0\0W\210\377\377\377\0\2\0\0\0#\0\0\0\211\223\0"
  "\0\0\310\3\0\0\0\266\0\0\0t\0\0\0\27\207\377\377\377\0\2\0\0\0\5\0\0"
  "\0\244\212\0\0\0\377\2\0\0\0\302\0\0\0\6\240\377\377\377\0\2\0\0\0\1"
  "\0\0\0\264\211\0\0\0\377\2\0\0\0\363\0\0\0""9\207\377\377\377\0\3\0\0"
  "\0\34\0\0\0\201\0\0\0\306\226\0\0\0\310\3\0\0\0\277\0\0\0Y\0\0\0\2\206"
  "\377\377\377\0\2\0\0\0\1\0\0\0\217\212\0\0\0\377\1\0\0\0\203\240\377"
  "\377\377\0\1\0\0\0\177\212\0\0\0\377\1\0\0\0T\206\377\377\377\0\3\0\0"
  "\0\25\0\0\0z\0\0\0\305\232\0\0\0\310\2\0\0\0\242\0\0\0*\207\377\377\377"
  "\0\1\0\0\0\243\211\0\0\0\377\2\0\0\0\372\0\0\0,\236\377\377\377\0\2\0"
  "\0\0D\0\0\0\375\211\0\0\0\377\1\0\0\0\213\206\377\377\377\0\2\0\0\0""8"
  "\0\0\0\274\235\0\0\0\310\3\0\0\0\306\0\0\0u\0\0\0\14\205\377\377\377"
  "\0\2\0\0\0\7\0\0\0\306\211\0\0\0\377\2\0\0\0\306\0\0\0\2\234\377\377"
  "\377\0\2\0\0\0\4\0\0\0\331\211\0\0\0\377\2\0\0\0\276\0\0\0\3\205\377"
  "\377\377\0\2\0\0\0T\0\0\0\306\214\0\0\0\310\10\0\0\0\260\0\0\0\202\0"
  "\0\0v\0\0\0~\0\0\0\207\0\0\0\217\0\0\0\227\0\0\0\264\214\0\0\0\310\2"
  "\0\0\0\264\0\0\0""2\205\377\377\377\0\2\0\0\0\27\0\0\0\341\211\0\0\0"
  "\377\1\0\0\0k\234\377\377\377\0\1\0\0\0c\211\0\0\0\377\2\0\0\0\343\0"
  "\0\0\26\204\377\377\377\0\2\0\0\0\2\0\0\0s\212\0\0\0\310\4\0\0\0\265"
  "\0\0\0s\0\0\0D\0\0\0\26\207\377\377\377\0\4\0\0\0\1\0\0\0+\0\0\0j\0\0"
  "\0\250\212\0\0\0\310\2\0\0\0\303\0\0\0A\205\377\377\377\0\2\0\0\0/\0"
  "\0\0\364\210\0\0\0\377\2\0\0\0\362\0\0\0\33\232\377\377\377\0\2\0\0\0"
  "\7\0\0\0\341\210\0\0\0\377\2\0\0\0\371\0\0\0""7\204\377\377\377\0\2\0"
  "\0\0\12\0\0\0\217\211\0\0\0\310\3\0\0\0\271\0\0\0]\0\0\0\10\216\377\377"
  "\377\0\3\0\0\0\36\0\0\0t\0\0\0\306\210\0\0\0\310\2\0\0\0\306\0\0\0P\205"
  "\377\377\377\0\1\0\0\0a\211\0\0\0\377\1\0\0\0\257\232\377\377\377\0\1"
  "\0\0\0n\211\0\0\0\377\1\0\0\0h\204\377\377\377\0\2\0\0\0\20\0\0\0\245"
  "\210\0\0\0\310\3\0\0\0\274\0\0\0c\0\0\0\12\222\377\377\377\0\2\0\0\0"
  "*\0\0\0\242\211\0\0\0\310\1\0\0\0`\205\377\377\377\0\1\0\0\0\276\211"
  "\0\0\0\377\1\0\0\0:\230\377\377\377\0\2\0\0\0\13\0\0\0\350\210\0\0\0"
  "\377\1\0\0\0\250\204\377\377\377\0\2\0\0\0\3\0\0\0\230\210\0\0\0\310"
  "\2\0\0\0\213\0\0\0\15\225\377\377\377\0\3\0\0\0\2\0\0\0Z\0\0\0\277\210"
  "\0\0\0\310\1\0\0\0U\204\377\377\377\0\2\0\0\0%\0\0\0\370\210\0\0\0\377"
  "\1\0\0\0\265\230\377\377\377\0\1\0\0\0y\210\0\0\0\377\2\0\0\0\372\0\0"
  "\0\40\204\377\377\377\0\1\0\0\0o\210\0\0\0\310\2\0\0\0o\0\0\0\2\230\377"
  "\377\377\0\2\0\0\0\30\0\0\0\226\207\0\0\0\310\2\0\0\0\306\0\0\0""7\204"
  "\377\377\377\0\1\0\0\0|\211\0\0\0\377\1\0\0\0""0\226\377\377\377\0\2"
  "\0\0\0\20\0\0\0\356\210\0\0\0\377\1\0\0\0\226\204\377\377\377\0\1\0\0"
  "\0C\207\0\0\0\310\2\0\0\0\305\0\0\0R\233\377\377\377\0\2\0\0\0\5\0\0"
  "\0\210\207\0\0\0\310\2\0\0\0\273\0\0\0\37\203\377\377\377\0\2\0\0\0\6"
  "\0\0\0\325\210\0\0\0\377\1\0\0\0\251\226\377\377\377\0\1\0\0\0\204\210"
  "\0\0\0\377\2\0\0\0\366\0\0\0\32\203\377\377\377\0\2\0\0\0!\0\0\0\277"
  "\206\0\0\0\310\2\0\0\0\275\0\0\0""8\235\377\377\377\0\2\0\0\0\2\0\0\0"
  "|\207\0\0\0\310\2\0\0\0\254\0\0\0\15\203\377\377\377\0\1\0\0\0J\210\0"
  "\0\0\377\2\0\0\0\375\0\0\0&\224\377\377\377\0\2\0\0\0\26\0\0\0\364\210"
  "\0\0\0\377\1\0\0\0\214\203\377\377\377\0\2\0\0\0\12\0\0\0\251\206\0\0"
  "\0\310\2\0\0\0\305\0\0\0""0\240\377\377\377\0\1\0\0\0r\207\0\0\0\310"
  "\1\0\0\0[\204\377\377\377\0\1\0\0\0\317\210\0\0\0\377\1\0\0\0\236\224"
  "\377\377\377\0\1\0\0\0\204\210\0\0\0\377\2\0\0\0\362\0\0\0\24\203\377"
  "\377\377\0\1\0\0\0\206\207\0\0\0\310\1\0\0\0X\214\377\377\377\0\11\0"
  "\0\0\5\0\0\0$\0\0\0G\0\0\0X\0\0\0T\0\0\0O\0\0\0K\0\0\0B\0\0\0\35\214"
  "\377\377\377\0\2\0\0\0\2\0\0\0\214\206\0\0\0\310\2\0\0\0\307\0\0\0""1"
  "\203\377\377\377\0\1\0\0\0V\210\0\0\0\377\2\0\0\0\372\0\0\0\27\223\377"
  "\377\377\0\1\0\0\0\271\210\0\0\0\377\1\0\0\0\202\203\377\377\377\0\1"
  "\0\0\0@\207\0\0\0\310\1\0\0\0\204\212\377\377\377\0\4\0\0\0\7\0\0\0E"
  "\0\0\0u\0\0\0\222\210\0\0\0\226\4\0\0\0\204\0\0\0T\0\0\0$\0\0\0\1\211"
  "\377\377\377\0\2\0\0\0\12\0\0\0\245\206\0\0\0\310\2\0\0\0\251\0\0\0\5"
  "\202\377\377\377\0\2\0\0\0\2\0\0\0\331\210\0\0\0\377\1\0\0\0C\223\377"
  "\377\377\0\1\0\0\0\342\207\0\0\0\377\2\0\0\0\356\0\0\0\17\202\377\377"
  "\377\0\2\0\0\0\2\0\0\0\246\206\0\0\0\310\2\0\0\0\246\0\0\0\11\210\377"
  "\377\377\0\3\0\0\0\5\0\0\0D\0\0\0\212\216\0\0\0\226\2\0\0\0z\0\0\0\40"
  "\211\377\377\377\0\2\0\0\0\32\0\0\0\274\206\0\0\0\310\1\0\0\0d\203\377"
  "\377\377\0\1\0\0\0a\210\0\0\0\377\1\0\0\0b\222\377\377\377\0\2\0\0\0"
  "\10\0\0\0\375\207\0\0\0\377\1\0\0\0x\203\377\377\377\0\1\0\0\0G\206\0"
  "\0\0\310\2\0\0\0\275\0\0\0\36\210\377\377\377\0\2\0\0\0""3\0\0\0\207"
  "\221\0\0\0\226\3\0\0\0\225\0\0\0X\0\0\0\11\210\377\377\377\0\1\0\0\0"
  "R\206\0\0\0\310\2\0\0\0\302\0\0\0\23\202\377\377\377\0\2\0\0\0\5\0\0"
  "\0\342\207\0\0\0\377\1\0\0\0\201\223\377\377\377\0\1\0\0\0m\206\0\0\0"
  "\377\2\0\0\0\321\0\0\0\12\202\377\377\377\0\2\0\0\0\3\0\0\0\254\206\0"
  "\0\0\310\1\0\0\0J\207\377\377\377\0\2\0\0\0\1\0\0\0O\210\0\0\0\226\1"
  "\0\0\0\206\202\0\0\0h\3\0\0\0m\0\0\0s\0\0\0\214\207\0\0\0\226\2\0\0\0"
  "\210\0\0\0)\207\377\377\377\0\2\0\0\0\1\0\0\0\233\206\0\0\0\310\1\0\0"
  "\0l\203\377\377\377\0\2\0\0\0P\0\0\0\374\205\0\0\0\377\2\0\0\0\337\0"
  "\0\0\"\224\377\377\377\0\1\0\0\0s\204\0\0\0\377\2\0\0\0\315\0\0\0\23"
  "\203\377\377\377\0\1\0\0\0N\206\0\0\0\310\2\0\0\0\245\0\0\0\2\206\377"
  "\377\377\0\2\0\0\0\6\0\0\0f\206\0\0\0\226\3\0\0\0w\0\0\0""7\0\0\0\23"
  "\205\377\377\377\0\4\0\0\0\3\0\0\0*\0\0\0[\0\0\0\212\205\0\0\0\226\2"
  "\0\0\0\222\0\0\0*\207\377\377\377\0\2\0\0\0#\0\0\0\304\205\0\0\0\310"
  "\2\0\0\0\277\0\0\0\16\203\377\377\377\0\2\0\0\0]\0\0\0\376\203\0\0\0"
  "\377\2\0\0\0\332\0\0\0\35\226\377\377\377\0\5\0\0\0;\0\0\0j\0\0\0\223"
  "\0\0\0\244\0\0\0\20\203\377\377\377\0\2\0\0\0\5\0\0\0\260\206\0\0\0\310"
  "\1\0\0\0>\206\377\377\377\0\2\0\0\0\14\0\0\0z\205\0\0\0\226\2\0\0\0|"
  "\0\0\0/\213\377\377\377\0\3\0\0\0\10\0\0\0U\0\0\0\224\204\0\0\0\226\2"
  "\0\0\0\221\0\0\0%\207\377\377\377\0\1\0\0\0s\206\0\0\0\310\1\0\0\0d\204"
  "\377\377\377\0\5\0\0\0a\0\0\0\240\0\0\0\177\0\0\0]\0\0\0\26\237\377\377"
  "\377\0\1\0\0\0U\206\0\0\0\310\1\0\0\0\235\206\377\377\377\0\2\0\0\0\2"
  "\0\0\0r\204\0\0\0\226\3\0\0\0\225\0\0\0J\0\0\0\1\216\377\377\377\0\2"
  "\0\0\0\35\0\0\0w\204\0\0\0\226\2\0\0\0\217\0\0\0\40\206\377\377\377\0"
  "\2\0\0\0\27\0\0\0\304\205\0\0\0\310\2\0\0\0\273\0\0\0\12\247\377\377"
  "\377\0\1\0\0\0\236\206\0\0\0\310\1\0\0\0""5\206\377\377\377\0\1\0\0\0"
  "T\204\0\0\0\226\2\0\0\0\221\0\0\0""3\221\377\377\377\0\2\0\0\0\4\0\0"
  "\0l\204\0\0\0\226\2\0\0\0\215\0\0\0\34\206\377\377\377\0\1\0\0\0}\206"
  "\0\0\0\310\1\0\0\0E\247\377\377\377\0\1\0\0\0\276\205\0\0\0\310\1\0\0"
  "\0\224\206\377\377\377\0\1\0\0\0""4\204\0\0\0\226\2\0\0\0\214\0\0\0\40"
  "\223\377\377\377\0\2\0\0\0\5\0\0\0q\204\0\0\0\226\2\0\0\0\211\0\0\0\14"
  "\205\377\377\377\0\2\0\0\0\37\0\0\0\306\205\0\0\0\310\1\0\0\0`\246\377"
  "\377\377\0\2\0\0\0\12\0\0\0\277\205\0\0\0\310\1\0\0\0+\205\377\377\377"
  "\0\2\0\0\0\30\0\0\0\220\203\0\0\0\226\2\0\0\0\225\0\0\0*\225\377\377"
  "\377\0\2\0\0\0\10\0\0\0v\204\0\0\0\226\1\0\0\0X\206\377\377\377\0\1\0"
  "\0\0\207\205\0\0\0\310\1\0\0\0m\247\377\377\377\0\2\0\0\0""3\0\0\0\301"
  "\203\0\0\0\310\1\0\0\0[\206\377\377\377\0\1\0\0\0n\204\0\0\0\226\1\0"
  "\0\0G\227\377\377\377\0\2\0\0\0\12\0\0\0z\203\0\0\0\226\2\0\0\0\224\0"
  "\0\0\27\205\377\377\377\0\2\0\0\0\20\0\0\0\246\203\0\0\0\310\2\0\0\0"
  "\224\0\0\0\11\250\377\377\377\0\4\0\0\0,\0\0\0h\0\0\0\210\0\0\0R\206"
  "\377\377\377\0\1\0\0\0&\204\0\0\0\226\2\0\0\0f\0\0\0\1\230\377\377\377"
  "\0\2\0\0\0\26\0\0\0\224\203\0\0\0\226\1\0\0\0g\206\377\377\377\0\5\0"
  "\0\0\22\0\0\0\206\0\0\0y\0\0\0]\0\0\0\6\263\377\377\377\0\1\0\0\0t\203"
  "\0\0\0\226\2\0\0\0\216\0\0\0\13\232\377\377\377\0\1\0\0\0X\204\0\0\0"
  "\226\1\0\0\0#\274\377\377\377\0\1\0\0\0-\204\0\0\0\226\1\0\0\0K\233\377"
  "\377\377\0\2\0\0\0\15\0\0\0\217\203\0\0\0\226\1\0\0\0v\274\377\377\377"
  "\0\1\0\0\0t\203\0\0\0\226\2\0\0\0\213\0\0\0\10\213\377\377\377\0\5\0"
  "\0\0\5\0\0\0\30\0\0\0\40\0\0\0\36\0\0\0\22\214\377\377\377\0\1\0\0\0"
  "J\204\0\0\0\226\1\0\0\0*\273\377\377\377\0\1\0\0\0`\203\0\0\0\226\1\0"
  "\0\0E\212\377\377\377\0\3\0\0\0\13\0\0\0@\0\0\0Y\204\0\0\0Z\3\0\0\0Q"
  "\0\0\0""1\0\0\0\5\211\377\377\377\0\2\0\0\0\6\0\0\0\207\203\0\0\0\226"
  "\1\0\0\0\26\273\377\377\377\0\5\0\0\0""1\0\0\0\226\0\0\0\224\0\0\0n\0"
  "\0\0\5\211\377\377\377\0\2\0\0\0$\0\0\0U\202\0\0\0Z\4\0\0\0P\0\0\0E\0"
  "\0\0I\0\0\0X\202\0\0\0Z\2\0\0\0P\0\0\0\33\211\377\377\377\0\4\0\0\0""3"
  "\0\0\0\206\0\0\0\226\0\0\0\201\274\377\377\377\0\3\0\0\0\6\0\0\0""8\0"
  "\0\0\13\211\377\377\377\0\2\0\0\0\7\0\0\0A\202\0\0\0Z\2\0\0\0I\0\0\0"
  "\20\203\377\377\377\0\6\0\0\0\4\0\0\0\37\0\0\0O\0\0\0Z\0\0\0Y\0\0\0\36"
  "\212\377\377\377\0\2\0\0\0\34\0\0\0)\310\377\377\377\0\5\0\0\0<\0\0\0"
  "Z\0\0\0Y\0\0\0.\0\0\0\2\206\377\377\377\0\5\0\0\0\3\0\0\0;\0\0\0Z\0\0"
  "\0X\0\0\0\32\322\377\377\377\0\1\0\0\0\34\202\0\0\0Z\1\0\0\0\30\211\377"
  "\377\377\0\5\0\0\0\1\0\0\0>\0\0\0Z\0\0\0W\0\0\0\13\320\377\377\377\0"
  "\4\0\0\0\5\0\0\0P\0\0\0Z\0\0\0""5\213\377\377\377\0\4\0\0\0\2\0\0\0H"
  "\0\0\0Z\0\0\0:\320\377\377\377\0\4\0\0\0""4\0\0\0Z\0\0\0P\0\0\0\5\214"
  "\377\377\377\0\1\0\0\0\26\202\0\0\0Z\1\0\0\0\22\317\377\377\377\0\3\0"
  "\0\0+\0\0\0X\0\0\0\33\216\377\377\377\0\3\0\0\0>\0\0\0I\0\0\0\23\320"
  "\377\377\377\0\1\0\0\0\12\217\377\377\377\0\2\0\0\0\6\0\0\0\1\377\377"
  "\377\377\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\377"
  "\377\377\377\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0"
  "\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\234\377\377\377"
  "\0"]

known_profile_icon = [ ""
  "GdkP"
  "\0\0\5""0"
  "\2\1\0\2"
  "\0\0\0P"
  "\0\0\0\24"
  "\0\0\0\24"
  "\210\0\0\0\0\4\0\0\0\3\0\0\0\16\0\0\0\23\0\0\0\11\216\0\0\0\0\11\0\0"
  "\0\16\0\0\0h\0\0\0\301\0\0\0\345\0\0\0\352\0\0\0\331\0\0\0\237\0\0\0"
  "9\0\0\0\3\212\0\0\0\0\13\0\0\0@\0\0\0\323\0\0\0\376\0\0\0\350\0\0\0\304"
  "\0\0\0\271\0\0\0\323\0\0\0\367\0\0\0\370\0\0\0\227\0\0\0\17\210\0\0\0"
  "\0\15\0\0\0K\0\0\0\354\0\0\0\365\0\0\0\206\0\0\0#\0\0\0\6\0\0\0\3\0\0"
  "\0\15\0\0\0C\0\0\0\304\0\0\0\376\0\0\0\260\0\0\0\22\206\0\0\0\0\17\0"
  "\0\0""2\0\0\0\346\0\0\0\351\0\0\0L\0\0\0#\0\0\0u\0\0\0\246\0\0\0\257"
  "\0\0\0\223\0\0\0M\0\0\0\27\0\0\0\235\0\0\0\375\0\0\0\242\0\0\0\7\204"
  "\0\0\0\0\20\0\0\0\13\0\0\0\300\0\0\0\372\0\0\0W\0\0\0O\0\0\0\271\0\0"
  "\0\233\0\0\0b\0\0\0V\0\0\0z\0\0\0\267\0\0\0\223\0\0\0$\0\0\0\267\0\0"
  "\0\374\0\0\0X\204\0\0\0\0\7\0\0\0S\0\0\0\374\0\0\0\240\0\0\0H\0\0\0\275"
  "\0\0\0a\0\0\0\12\202\0\0\0\0\10\0\0\0\1\0\0\0%\0\0\0\240\0\0\0\241\0"
  "\0\0""9\0\0\0\352\0\0\0\320\0\0\0\12\203\0\0\0\0\21\0\0\0\262\0\0\0\351"
  "\0\0\0A\0\0\0\272\0\0\0g\0\0\0\6\0\0\0""4\0\0\0e\0\0\0l\0\0\0T\0\0\0"
  "\25\0\0\0\27\0\0\0\251\0\0\0v\0\0\0\214\0\0\0\367\0\0\0<\203\0\0\0\0"
  "\21\0\0\0""6\0\0\0G\0\0\0r\0\0\0\244\0\0\0\17\0\0\0P\0\0\0b\0\0\0#\0"
  "\0\0\27\0\0\0;\0\0\0s\0\0\0\33\0\0\0E\0\0\0\270\0\0\0""6\0\0\0\\\0\0"
  "\0\15\205\0\0\0\0\15\0\0\0T\0\0\0""8\0\0\0""0\0\0\0f\0\0\0\6\0\0\0\0"
  "\0\0\0\1\0\0\0\0\0\0\0(\0\0\0l\0\0\0\13\0\0\0k\0\0\0\33\206\0\0\0\0\16"
  "***;\210\210\210\356\223\223\223\377iii\377\204\204\204\377\216\216\216"
  "\377~~~\377zzz\377\203\203\203\377\215\215\215\377ddd\377\202\202\202"
  "\377xxx\356\40\40\40;\205\0\0\0\0\2&&&#\251\251\251\353\202\374\374\374"
  "\377\202\372\372\372\377\5\335\335\335\377\353\353\353\377\366\366\366"
  "\377\327\327\327\377\357\357\357\377\202\365\365\365\377\3\362\362\362"
  "\377\226\226\226\353\27\27\27)\204\0\0\0\0\21,,,p\354\354\354\377\355"
  "\355\355\377\351\351\351\377\346\346\346\377\342\342\342\377\335\335"
  "\335\377\334\334\334\377\330\330\330\377\324\324\324\377\320\320\320"
  "\377\316\316\316\377\313\313\313\377\307\307\307\377\314\314\314\377"
  "\35\35\35y\0\0\0\1\202\0\0\0\0\14\0\0\0\2(((\203\357\357\357\377\345"
  "\345\345\377\341\341\341\377\337\337\337\377\333\333\333\377\326\326"
  "\326\377\322\322\322\377\316\316\316\377\312\312\312\377\306\306\306"
  "\377\202\302\302\302\377\30\314\314\314\377\311\311\311\377\33\33\33"
  "\204\0\0\0\5\0\0\0\1\0\0\0\2\0\0\0\10&&&\210\356\356\356\377\342\342"
  "\342\377\347\347\347\377\346\346\346\377\324GG\377\337\337\337\377\324"
  "GG\377\333\322\322\377\324GG\377<\341@\377\324GG\377<\341@\377\321\321"
  "\321\377\276\276\276\377\27\27\27\214\0\0\0\15\202\0\0\0\4+\0\0\0\21"
  "$$$\221\355\355\355\377\345\345\345\377\344\344\344\377\340\340\340\377"
  "\334\334\334\377\331\331\331\377\325\325\325\377\321\321\321\377\316"
  "\316\316\377\312\312\312\377\306\306\306\377\307\307\307\377\313\313"
  "\313\377\272\272\272\377\24\24\24\226\0\0\0\30\0\0\0\10\0\0\0\5\0\0\0"
  "\27\"\"\"\231\354\354\354\377\346\346\346\377\342\342\342\377\337\337"
  "\337\377\333\333\333\377\327\327\327\377\324\324\324\377\320\320\320"
  "\377\314\314\314\377\310\310\310\377\305\305\305\377\301\301\301\377"
  "\276\276\276\377\271\271\271\377\23\23\23\235\0\0\0\35\0\0\0\10\0\0\0"
  "\4\0\0\0\32\40\40\40\223\310\310\310\376\202\274\274\274\377\4\272\272"
  "\272\377\271\271\271\377\270\270\270\377\267\267\267\377\202\271\271"
  "\271\377\16\270\270\270\377\266\266\266\377\265\265\265\377\264\264\264"
  "\377\231\231\231\376\16\16\16\240\0\0\0\35\0\0\0\6\0\0\0\2\0\0\0\12\0"
  "\0\0/\0\0\0n\0\0\0|\0\0\0\177\202\0\0\0\200\202\0\0\0\201\1\0\0\0\203"
  "\204\0\0\0\205\12\0\0\0\201\0\0\0y\0\0\0<\0\0\0\15\0\0\0\2\0\0\0\0\0"
  "\0\0\2\0\0\0\6\0\0\0\14\0\0\0\20\204\0\0\0\24\202\0\0\0\25\203\0\0\0"
  "\26\6\0\0\0\25\0\0\0\22\0\0\0\15\0\0\0\7\0\0\0\2\0\0\0\0"]

unknown_profile_icon = [ ""
  "GdkP"
  "\0\0\5\22"
  "\2\1\0\2"
  "\0\0\0P"
  "\0\0\0\24"
  "\0\0\0\24"
  "\210\0\0\0\0\4\0\0\0\1\0\0\0\4\0\0\0\6\0\0\0\3\216\0\0\0\0\11\0\0\0\4"
  "\0\0\0\37\0\0\0""9\0\0\0D\0\0\0F\0\0\0@\0\0\0/\0\0\0\21\0\0\0\1\212\0"
  "\0\0\0\7\0\0\0\23\0\0\0\77\0\0\0K\0\0\0E\0\0\0:\0\0\0""7\0\0\0\77\202"
  "\0\0\0I\2\0\0\0-\0\0\0\4\210\0\0\0\0\15\0\0\0\26\0\0\0F\0\0\0I\0\0\0"
  "(\0\0\0\13\0\0\0\2\0\0\0\1\0\0\0\4\0\0\0\24\0\0\0:\0\0\0K\0\0\0""4\0"
  "\0\0\6\206\0\0\0\0\17\0\0\0\17\0\0\0D\0\0\0E\0\0\0\26\0\0\0\13\0\0\0"
  "#\0\0\0""1\0\0\0""4\0\0\0,\0\0\0\27\0\0\0\7\0\0\0/\0\0\0K\0\0\0""0\0"
  "\0\0\2\204\0\0\0\0\20\0\0\0\3\0\0\0""9\0\0\0J\0\0\0\32\0\0\0\30\0\0\0"
  "7\0\0\0.\0\0\0\35\0\0\0\32\0\0\0$\0\0\0""6\0\0\0,\0\0\0\13\0\0\0""6\0"
  "\0\0K\0\0\0\32\204\0\0\0\0\7\0\0\0\31\0\0\0K\0\0\0""0\0\0\0\25\0\0\0"
  "8\0\0\0\35\0\0\0\3\202\0\0\0\0\2\0\0\0\1\0\0\0\13\202\0\0\0""0\4\0\0"
  "\0\21\0\0\0F\0\0\0>\0\0\0\3\203\0\0\0\0\21\0\0\0""5\0\0\0E\0\0\0\23\0"
  "\0\0""7\0\0\0\37\0\0\0\2\0\0\0\20\0\0\0\36\0\0\0\40\0\0\0\31\0\0\0\6"
  "\0\0\0\7\0\0\0""2\0\0\0#\0\0\0)\0\0\0I\0\0\0\22\203\0\0\0\0\21\0\0\0"
  "\20\0\0\0\25\0\0\0\"\0\0\0""1\0\0\0\4\0\0\0\30\0\0\0\35\0\0\0\13\0\0"
  "\0\7\0\0\0\21\0\0\0\"\0\0\0\10\0\0\0\25\0\0\0""6\0\0\0\20\0\0\0\33\0"
  "\0\0\4\205\0\0\0\0\15\0\0\0\31\0\0\0\21\0\0\0\16\0\0\0\36\0\0\0\2\0\0"
  "\0\0\0\0\0\1\0\0\0\0\0\0\0\14\0\0\0\40\0\0\0\3\0\0\0\40\0\0\0\10\206"
  "\0\0\0\0\16***\21\210\210\210G\223\223\223LiiiL\204\204\204L\34=n\300"
  "\14""1i\361\12""0i\374\20""4j\342CXx}dddL\202\202\202LxxxG\40\40\40\21"
  "\205\0\0\0\0\2&&&\13\251\251\251F\202\374\374\374L\202\372\372\372L\5"
  "\"Cv\310Lf\217\226@]\211\245\12""0i\377\22""7n\353\202\365\365\365L\3"
  "\362\362\362L\226\226\226F\27\27\27\14\204\0\0\0\0\21,,,!\354\354\354"
  "L\355\355\355L\351\351\351L\346\346\346L\342\342\342L\335\335\335L\334"
  "\334\334L\210\227\255h\12""0i\377\21""6l\352\316\316\316L\313\313\313"
  "L\307\307\307L\314\314\314L\35\35\35$\0\0\0\1\202\0\0\0\0\14\0\0\0\1"
  "((('\357\357\357L\345\345\345L\341\341\341L\337\337\337L\333\333\333"
  "L\326\326\326L|\215\245l\20""5l\355\12""0i\374Sj\215\205\202\302\302"
  "\302L\4\314\314\314L\311\311\311L\33\33\33'\0\0\0\2\202\0\0\0\1\22\0"
  "\0\0\2&&&(\356\356\356L\342\342\342L\347\347\347L\346\346\346L\324GG"
  "L\337\337\337L\22""0g\351\12""0i\377^9Z\201<\341@L\324GGL<\341@L\321"
  "\321\321L\276\276\276L\27\27\27)\0\0\0\4\202\0\0\0\1\22\0\0\0\5$$$+\355"
  "\355\355L\345\345\345L\344\344\344L\340\340\340L\334\334\334L\331\331"
  "\331Law\227\177`u\226\177\316\316\316L\312\312\312L\306\306\306L\307"
  "\307\307L\313\313\313L\272\272\272L\24\24\24,\0\0\0\7\202\0\0\0\2\27"
  "\0\0\0\7\"\"\"-\354\354\354L\346\346\346L\342\342\342L\337\337\337L\333"
  "\333\333L\327\327\327LSk\217\212Qi\216\212\314\314\314L\310\310\310L"
  "\305\305\305L\301\301\301L\276\276\276L\271\271\271L\23\23\23/\0\0\0"
  "\10\0\0\0\2\0\0\0\1\0\0\0\10\40\40\40,\310\310\310K\202\274\274\274L"
  "\3\272\272\272L\271\271\271L\270\270\270L\202\12""0i\377\16\271\271\271"
  "L\270\270\270L\266\266\266L\265\265\265L\264\264\264L\231\231\231K\16"
  "\16\16""0\0\0\0\10\0\0\0\2\0\0\0\1\0\0\0\3\0\0\0\16\0\0\0!\0\0\0%\205"
  "\0\0\0&\205\0\0\0'\12\0\0\0&\0\0\0$\0\0\0\22\0\0\0\4\0\0\0\1\0\0\0\0"
  "\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\4\206\0\0\0\6\203\0\0\0\7\202\0\0\0\6"
  "\4\0\0\0\4\0\0\0\2\0\0\0\1\0\0\0\0"]

signal_xpm_barely = [
"20 20 10 1",
" 	c None",
".	c #C6C6C6",
"+	c #CCCCCC",
"@	c #DBDBDB",
"#	c #D3D3D3",
"$	c #A9B099",
"%	c #95A173",
"&	c #6B8428",
"*	c #B4B7AC",
"=	c #80924D",
"               .+++.",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"          .++++#@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"     $%%%%#@@@@@@@@+",
"     %&&&&@@@@@@@@@+",
"     %&&&&@@@@@@@@@+",
"     %&&&&@@@@@@@@@+",
"     %&&&&@@@@@@@@@+",
"*%%%%=&&&&@@@@@@@@@+",
"%&&&&&&&&&@@@@@@@@@+",
"%&&&&&&&&&@@@@@@@@@+",
"%&&&&&&&&&@@@@@@@@@+",
"*%%%%%%%%%+++++++++."
]


signal_xpm_best = [
"20 20 6 1",
" 	c None",
".	c #9DAABF",
"+	c #7B96BF",
"@	c #386EBF",
"#	c #5982BF",
"$	c #AEB4BF",
"               .+++.",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"          .++++#@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"     .++++#@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"$++++#@@@@@@@@@@@@@+",
"+@@@@@@@@@@@@@@@@@@+",
"+@@@@@@@@@@@@@@@@@@+",
"+@@@@@@@@@@@@@@@@@@+",
"$++++++++++++++++++."
]

signal_xpm_none = [
"20 20 6 1",
" 	c None",
".	c #C6C6C6",
"+	c #CCCCCC",
"@	c #DBDBDB",
"#	c #D3D3D3",
"$	c #C2C2C2",
"               .+++.",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"          .++++#@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"     .++++#@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"$++++#@@@@@@@@@@@@@+",
"+@@@@@@@@@@@@@@@@@@+",
"+@@@@@@@@@@@@@@@@@@+",
"+@@@@@@@@@@@@@@@@@@+",
"$++++++++++++++++++."
]

signal_xpm_ok = [
"20 20 10 1",
" 	c None",
".	c #C6C6C6",
"+	c #CCCCCC",
"@	c #DBDBDB",
"#	c #A1A5B2",
"$	c #848DA5",
"%	c #D3D3D3",
"&	c #4A5B8C",
"*	c #677498",
"=	c #B0B2B8",
"               .+++.",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"          #$$$$%@@@+",
"          $&&&&@@@@+",
"          $&&&&@@@@+",
"          $&&&&@@@@+",
"          $&&&&@@@@+",
"     #$$$$*&&&&@@@@+",
"     $&&&&&&&&&@@@@+",
"     $&&&&&&&&&@@@@+",
"     $&&&&&&&&&@@@@+",
"     $&&&&&&&&&@@@@+",
"=$$$$*&&&&&&&&&@@@@+",
"$&&&&&&&&&&&&&&@@@@+",
"$&&&&&&&&&&&&&&@@@@+",
"$&&&&&&&&&&&&&&@@@@+",
"=$$$$$$$$$$$$$$++++."
]


signal_xpm_low = [
"20 20 8 1",
" 	c None",
".	c #C6C6C6",
"+	c #CCCCCC",
"@	c #DBDBDB",
"#	c #D3D3D3",
"$	c #BFB0B5",
"%	c #C18799",
"&	c #C54F74",
"               .+++.",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"               +@@@+",
"          .++++#@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"          +@@@@@@@@+",
"     .++++#@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"     +@@@@@@@@@@@@@+",
"$%%%%#@@@@@@@@@@@@@+",
"%&&&&@@@@@@@@@@@@@@+",
"%&&&&@@@@@@@@@@@@@@+",
"%&&&&@@@@@@@@@@@@@@+",
"$%%%%++++++++++++++."
]
signal_none_pb	= None
signal_low_pb	= None
signal_barely_pb= None
signal_ok_pb	= None
signal_best_pb	= None
exit_flag		= False
current_ip		= ''
current_ssid	= ''
####################################################################################################
# Make so we can be imported
if __name__ == "__main__":
	# Are we in configure mode?
	if len( sys.argv ) > 1 and ( sys.argv[1] == '--version' or sys.argv[1] == '-v' ):
		print "WiFi-Radar version %s" % WIFI_RADAR_VERSION
	elif len( sys.argv ) > 1 and ( sys.argv[1] == '--daemon' or sys.argv[1] == '-d' ):
		scanning_thread()
		connect_to_preferred()
	else:
		import gtk, gobject
		gtk.threads_init()
		configure()
