4 # vi:set filetype=python noet:
6 # A wireless profile manager for Linux
8 # Originally created for x1000 Linux:
9 # http://x1000.bitbuilder.com
12 # Ahmad Baitalmal <ahmad@baitalmal.com>
15 # Brian Elliott Finley <brian@thefinleys.com>
20 # http://www.bitbuilder.com/wifi_radar
21 # http://svn.systemimager.org
23 # See CREDITS file for more contributors.
24 # See ChangeLog file for, well, changes.
27 import time
, os
, signal
, sys
, re
, ConfigParser
, threading
, socket
, string
30 WIFI_RADAR_VERSION
= "0.0.0"
33 print '__debug__ is True'
34 # NOTE: Remove the '-OO' from '#!/usr/bin/python -OO' in the first line to
38 # Where the conf file should live could be different for your distro. Please change
39 # at install time with "make install sysconfdir=/etc/wifi-radar" or similar. -BEF-
41 CONF_FILE
= "/etc/wifi-radar.conf"
43 os
.environ
['LC_MESSAGES'] = 'C'
45 if os
.path
.isfile(CONF_FILE
) and not os
.access(CONF_FILE
, os
.R_OK
):
46 print "Can't open " + CONF_FILE
+ "."
51 HOSTNAME
= socket
.gethostname()
54 #####################################
56 USE_DHCP_LABEL
= "Automatic network configuration (DHCP)"
57 USE_IP_LABEL
= "Manual network configuration"
58 WIFI_SET_LABEL
= "WiFi Options"
59 CON_PP_LABEL
= "Connection Commands"
60 DIS_PP_LABEL
= "Disconnection Commands"
61 USE_WPA_LABEL
= "Use WPA"
62 NO_WPA_LABEL
= "No WPA"
63 WIFI_MODES
= [ '', 'auto', 'Managed', 'Ad-Hoc', 'Master', 'Repeater', 'Secondary', 'Monitor' ]
64 WIFI_SECURITY
= [ '', 'open', 'restricted' ]
65 WIFI_CHANNELS
= [ '', 'auto', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14' ]
66 ####################################################################################################
68 ####################################################################################################
69 ####################################################################################################
71 # Sets the interface to the specified network device
72 def set_network_device(device
):
73 #print "set_network_device: ", device
74 if device
!= "auto_detect":
75 confFile
.set_opt('DEFAULT.interface', device
)
76 else: # auto detect network device
77 # Get a list of 802.11 enabled devices by parsing the output of iwconfig.
78 # If no devices are found, default to eth1.
79 iwconfig_info
= os
.popen(confFile
.get_opt('DEFAULT.iwconfig_command') + " 2>&1", 'r')
80 wireless_devices
= [ (x
[0:x
.find(" ")]) for x
in iwconfig_info
if("ESSID" in x
)]
81 if len(wireless_devices
) > 0:
82 confFile
.set_opt('DEFAULT.interface', wireless_devices
[0])
84 print "No wifi-device found. Exiting."
87 # Scan for a limited time, return ap names and bssid found
88 def scanning_thread( confFile
, lock
= None ):
90 global main_radar_window
92 # Setup our essid pattern matcher
93 essid_pattern
= re
.compile( "ESSID\s*(:|=)\s*\"([^\"]+)\"", re
.I | re
.M | re
.S
)
94 protocol_pattern
= re
.compile( "Protocol\s*(:|=)\s*IEEE 802.11\s*([abg]+)", re
.I | re
.M | re
.S
)
95 mode_pattern
= re
.compile( "Mode\s*(:|=)\s*([^\n]+)", re
.I | re
.M | re
.S
)
96 channel_pattern
= re
.compile( "Channel\s*(:|=)*\s*(\d+)", re
.I | re
.M | re
.S
)
97 enckey_pattern
= re
.compile( "Encryption key\s*(:|=)\s*(on|off)", re
.I | re
.M | re
.S
)
98 signal_pattern
= re
.compile( "Signal level\s*(:|=)\s*-?([0-9]+)", re
.I | re
.M | re
.S
)
99 # Access points we find will be added to the access_points dictionary
100 # Some cards neet to have the interface up to scan
101 if confFile
.get_opt_as_bool('DEFAULT.ifup_required'):
102 os
.spawnlp(os
.P_WAIT
, 'ifconfig', confFile
.get_opt('DEFAULT.ifconfig_command'), confFile
.get_opt('DEFAULT.interface'), "up")
105 # we may not be running in a thread
110 if trial
> confFile
.get_opt_as_int('DEFAULT.scan_timeout'):
116 if None != lock
: lock
.release()
122 # update the signal strengths
123 scan_command
= "%s %s scan" % ( confFile
.get_opt('DEFAULT.iwlist_command'), confFile
.get_opt('DEFAULT.interface') )
124 f
= os
.popen(scan_command
, "r")
128 print "Current IP ", get_current_ip()
129 print "Current ESSID ", get_current_essid()
130 print "Current BSSID ", get_current_bssid()
131 for ap
in access_points
:
132 access_points
[ ap
]['signal'] = '0'
133 # split the scan data based on the address
134 hits
= scandata
.split( '- Address:' )
143 m
= essid_pattern
.search( hit
)
147 essid
= m
.groups()[1]
148 m
= bssid_pattern
.search( hit
) # get BSSID from scan
150 bssid
= m
.groups()[1]
151 m
= protocol_pattern
.search( hit
) # get protocol from scan
153 protocol
= m
.groups()[1]
154 m
= mode_pattern
.search( hit
) # get Mode from scan
157 m
= channel_pattern
.search( hit
) # get channel from scan
159 channel
= m
.groups()[1]
160 m
= enckey_pattern
.search( hit
) # get Encryption Key from scan
162 encrypted
= m
.groups()[1]
163 m
= signal_pattern
.search( hit
) # get signal strength from scan
165 signal
= m
.groups()[1]
166 ap
= make_section_name( essid
, bssid
)
167 # Set the values we found
168 if access_points
.has_key( ap
):
169 # We know this AP, make it available
170 access_points
[ ap
]['available'] = True
172 # Add it to the available networks
174 new_ap
['known'] = False
175 new_ap
['available'] = True
176 access_points
[ ap
] = new_ap
177 access_points
[ ap
]['essid'] = essid
178 access_points
[ ap
]['bssid'] = bssid
179 access_points
[ ap
]['protocol'] = protocol
180 access_points
[ ap
]['mode'] = mode
181 access_points
[ ap
]['channel'] = channel
182 access_points
[ ap
]['encrypted'] = ( encrypted
== 'on' )
183 access_points
[ ap
]['signal'] = signal
187 if confFile
.get_opt('DEFAULT.interface').find('ath') == 0:
193 # Connects to the first matching network
194 def connect_to_preferred():
196 global auto_profile_order
199 lock
= threading
.RLock()
202 for ap
in auto_profile_order
:
204 if access_points
.has_key( ap
) \
205 and access_points
[ ap
]['known'] \
206 and access_points
[ ap
]['available']:
208 connect_to_network( access_points
[ ap
]['essid'], access_points
[ ap
]['bssid'], None )
212 say( "No preferred network found" )
214 print " No preferred network found"
217 def get_current_ip():
218 """Returns the current IP if any by calling ifconfig"""
219 ifconfig_info
= os
.popen(confFile
.get_opt('DEFAULT.ifconfig_command') + " " + confFile
.get_opt('DEFAULT.interface'), 'r')
220 # Be careful to the language (inet adr: in French for example)
224 # I'm using wifi-radar on a system with German translations (de_CH-UTF-8).
225 # There the string in ifconfig is inet Adresse for the IP which isn't
226 # found by the current get_current_ip function in wifi-radar. I changed
227 # the according line (#289; gentoo, v1.9.6-r1) to
228 # >ip_re = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)')
229 # which works on my system (LC_ALL=de_CH.UTF-8) and still works with LC_ALL=C.
231 # I'd be happy if you could incorporate this small change because as now
232 # I've got to change the file every time it is updated.
237 ip_re
= re
.compile(r
'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)')
238 for line
in ifconfig_info
:
239 if ip_re
.search( line
):
240 return ip_re
.search( line
).group(1)
243 def get_current_essid():
244 """Returns the current ESSID if any by calling iwconfig"""
245 iwconfig_info
= os
.popen(confFile
.get_opt('DEFAULT.iwconfig_command') + " " + confFile
.get_opt('DEFAULT.interface'), 'r')
246 # Be careful to the language (inet adr: in French for example)
247 essid_re
= re
.compile( "ESSID\s*(:|=)\s*\"([^\"]+)\"", re
.I | re
.M | re
.S
)
248 for line
in iwconfig_info
:
249 if essid_re
.search( line
):
250 return essid_re
.search( line
).group(2)
253 def get_current_bssid():
254 """Returns the current BSSID if any by calling iwconfig"""
255 iwconfig_info
= os
.popen(confFile
.get_opt('DEFAULT.iwconfig_command') + " " + confFile
.get_opt('DEFAULT.interface'), 'r')
256 bssid_re
= re
.compile( "Access Point\s*(:|=)\s*([a-zA-Z0-9:]+)", re
.I | re
.M | re
.S
)
257 for line
in iwconfig_info
:
258 if bssid_re
.search( line
):
259 return bssid_re
.search( line
).group(2)
262 def connect_to_network( essid
, bssid
, status_win
):
263 msg
= "Connecting to the %s (%s) network" % (essid
, bssid
)
267 profile
= get_profile_from_conf_file( essid
, bssid
)
270 print "Unknown ESSID"
271 say( "Unknown ESSID" )
274 # Let's run the connection prescript
275 con_prescript
= profile
['con_prescript']
276 if con_prescript
.strip() != '':
277 # got something to execute
279 print "executing connection prescript:", con_prescript
280 os
.system(con_prescript
)
281 # Some cards need to have the interface up
282 if confFile
.get_opt_as_bool('DEFAULT.ifup_required'):
283 os
.spawnlp(os
.P_WAIT
, 'ifconfig', confFile
.get_opt('DEFAULT.ifconfig_command'), confFile
.get_opt('DEFAULT.interface'), "up")
284 iwconfig_args
= [ confFile
.get_opt('DEFAULT.interface') ]
285 # Let's start with the essid
287 print "Setting essid ", essid
288 iwconfig_args
.append( 'essid' )
289 iwconfig_args
.append( '"%s"' % essid
)
290 iwconfig_args
.append( 'nick' )
291 iwconfig_args
.append( '"%s"' % essid
)
292 #os.spawnlp(os.P_WAIT, 'iwconfig', confFile.get_opt('DEFAULT.iwconfig_command'), confFile.get_opt('DEFAULT.interface'), 'essid', "%s" % essid)
298 key
= "%s %s" % ( profile
['security'], profile
['key'], )
300 print "Setting key", key
301 #os.spawnlp(os.P_WAIT, 'iwconfig', confFile.get_opt('DEFAULT.iwconfig_command'), confFile.get_opt('DEFAULT.interface'), 'key', key)
302 iwconfig_args
.append( 'key' )
303 iwconfig_args
.append( key
)
305 mode
= profile
['mode']
308 print "Setting mode ", mode
309 #os.spawnlp(os.P_WAIT, 'iwconfig', confFile.get_opt('DEFAULT.iwconfig_command'), confFile.get_opt('DEFAULT.interface'), 'mode', mode)
310 iwconfig_args
.append( 'mode' )
311 iwconfig_args
.append( mode
)
313 channel
= profile
['channel']
316 print "Setting channel ", channel
317 #os.spawnlp(os.P_WAIT, 'iwconfig', confFile.get_opt('DEFAULT.iwconfig_command'), confFile.get_opt('DEFAULT.interface'), 'channel', channel)
318 iwconfig_args
.append( 'channel' )
319 iwconfig_args
.append( channel
)
320 # Now we do the ap by address (do this last since iwconfig seems to want it only there)
322 print "Setting bssid ", profile
['bssid']
323 iwconfig_args
.append( 'ap' )
324 iwconfig_args
.append( '"%s"' % profile
['bssid'] )
325 # Some cards require a commit
326 if confFile
.get_opt_as_bool('DEFAULT.commit_required'):
328 print "Setting commit "
329 #os.spawnlp(os.P_WAIT, 'iwconfig', confFile.get_opt('DEFAULT.iwconfig_command'), confFile.get_opt('DEFAULT.interface'), 'commit')
330 iwconfig_args
.append( 'commit' )
332 print "iwconfig_args %s " % ( iwconfig_args
, )
333 iwconfig_command
= confFile
.get_opt('DEFAULT.iwconfig_command') + ' ' + ' '.join( iwconfig_args
)
334 #os.spawnvp(os.P_WAIT, 'iwconfig', iwconfig_args)
336 print "iwconfig_command ", iwconfig_command
337 os
.system(iwconfig_command
)
338 # Now normal network stuff
339 # Kill off any existing DHCP clients running
340 if os
.access(confFile
.get_opt('DHCP.pidfile'), os
.R_OK
):
342 print "Killing existing DHCP..."
344 if confFile
.get_opt('DHCP.kill_args') != '':
346 print confFile
.get_opt('DHCP.command') + " " + confFile
.get_opt('DHCP.kill_args')
347 os
.popen(confFile
.get_opt('DHCP.command') + " " + confFile
.get_opt('DHCP.kill_args'))
349 os
.kill(int(open(confFile
.get_opt('DHCP.pidfile'), mode
='r').readline()), signal
.SIGTERM
)
351 print "Stale pid file. Removing"
352 os
.remove(confFile
.get_opt('DHCP.pidfile'))
353 if os
.path
.isfile(confFile
.get_opt('DHCP.pidfile')):
354 print "Stale pid file. Removing"
355 os
.remove(confFile
.get_opt('DHCP.pidfile'))
356 if os
.access(confFile
.get_opt('WPA.pidfile'), os
.R_OK
):
358 print "Killing existing WPA_SUPPLICANT..."
360 if not confFile
.get_opt('WPA.kill_command') == '':
361 os
.spawnlp(os
.P_WAIT
, confFile
.get_opt('WPA.kill_command'), confFile
.get_opt('WPA.kill_command'))
362 os
.kill(int(open(confFile
.get_opt('WPA.pidfile'), mode
='r').readline()), signal
.SIGTERM
)
364 print "Stale pid file. Removing"
365 os
.remove(confFile
.get_opt('WPA.pidfile'))
366 if os
.path
.isfile(confFile
.get_opt('WPA.pidfile')):
367 print "Stale pid file. Removing"
368 os
.remove(confFile
.get_opt('WPA.pidfile'))
369 use_wpa
= profile
['use_wpa']
372 wpa_options
.append( confFile
.get_opt('WPA.command') )
373 wpa_args
= "-B -i " + confFile
.get_opt('DEFAULT.interface') + " -c " + confFile
.get_opt('WPA.configuration') + " -D " + profile
['wpa_driver'] + " -P " + confFile
.get_opt('WPA.pidfile')
374 wpa_options
.extend( wpa_args
.split() )
375 wpa_options
.append( confFile
.get_opt('DEFAULT.interface') )
377 print "WPA args: %s" % ( wpa_options
, )
379 status_win
.update_message("wpa supplicant")
380 wpa_pid
= os
.spawnvp(os
.P_NOWAIT
, confFile
.get_opt('WPA.command'), wpa_options
)
382 use_dhcp
= profile
['use_dhcp']
384 dhcp_options
= list()
385 dhcp_options
.append(confFile
.get_opt('DHCP.command'))
386 dhcp_options
.extend(confFile
.get_opt('DHCP.args').split())
387 dhcp_options
.append(confFile
.get_opt('DEFAULT.interface'))
389 print "DHCP args: %s" % ( dhcp_options
, )
391 status_win
.update_message("Acquiring IP Address")
393 # Disable iwlist while dhcp in progress
395 print "Disable iwlist while dhcp in progress..."
399 dhcp_pid
= os
.spawnvp(os
.P_NOWAIT
, confFile
.get_opt('DHCP.command'), dhcp_options
)
400 timer
= confFile
.get_opt_as_int('DHCP.timeout')
402 while os
.waitpid(dhcp_pid
, os
.WNOHANG
) == (0,0):
404 os
.kill(dhcp_pid
, signal
.SIGTERM
)
406 if sys
.modules
.has_key("gtk"):
407 while gtk
.events_pending():
408 gtk
.main_iteration(False)
415 if not get_current_ip():
417 status_win
.update_message("Could not get IP address!")
418 if sys
.modules
.has_key("gtk"):
419 while gtk
.events_pending():
420 gtk
.main_iteration(False)
423 print "Could not get IP address!"
427 status_win
.update_message("Got IP address. Done")
428 if sys
.modules
.has_key("gtk"):
429 while gtk
.events_pending():
430 gtk
.main_iteration(False)
434 netmask
= profile
['netmask']
435 gateway
= profile
['gateway']
436 domain
= profile
['domain']
437 dns1
= profile
['dns1']
438 dns2
= profile
['dns2']
439 ifconfig_command
= "%s %s down; %s %s %s netmask %s" % \
440 ( confFile
.get_opt('DEFAULT.ifconfig_command'), confFile
.get_opt('DEFAULT.interface'), confFile
.get_opt('DEFAULT.ifconfig_command'), confFile
.get_opt('DEFAULT.interface'), ip
, netmask
)
441 route_command
= "%s add default gw %s" % ( confFile
.get_opt('DEFAULT.route_command'), gateway
)
444 s
+= "domain %s\n" % domain
446 s
+= "nameserver %s\n" % dns1
448 s
+= "nameserver %s\n" % dns2
450 f
=open('/etc/resolv.conf', 'w')
454 os
.system(ifconfig_command
)
455 os
.system(route_command
)
457 # Let's run the connection postscript
458 con_postscript
= profile
['con_postscript']
459 if con_postscript
.strip() != '':
460 # got something to execute
462 print "executing connection postscript:", con_postscript
463 os
.system(con_postscript
)
465 def disconnect_interface():
466 msg
= "Disconnecting"
470 profile
= get_profile_from_conf_file( get_current_essid(), get_current_bssid() )
473 print "Unknown ESSID"
474 say( "Unknown ESSID" )
476 # Kill off any existing DHCP clients running
477 # Let's run the disconnection prescript
478 dis_prescript
= profile
['dis_prescript']
479 if dis_prescript
.strip() != '':
480 # got something to execute
482 print "executing disconnection prescript:", dis_prescript
483 os
.system(dis_prescript
)
484 # Kill off any existing DHCP clients running
486 if confFile
.get_opt('DHCP.kill_args') != '':
488 print confFile
.get_opt('DHCP.command') + " " + confFile
.get_opt('DHCP.kill_args')
489 os
.popen(confFile
.get_opt('DHCP.command') + " " + confFile
.get_opt('DHCP.kill_args'))
491 if os
.access(confFile
.get_opt('DHCP.pidfile'), os
.R_OK
):
493 print "Killing existing DHCP..."
495 os
.kill(int(open(confFile
.get_opt('DHCP.pidfile'), mode
='r').readline()), signal
.SIGTERM
)
497 print "Stale pid file. Removing"
498 os
.remove(confFile
.get_opt('DHCP.pidfile'))
499 if os
.path
.isfile(confFile
.get_opt('DHCP.pidfile')):
500 print "Stale pid file. Removing"
501 os
.remove(confFile
.get_opt('DHCP.pidfile'))
502 # Kill off any existing WPA_SUPPLICANT clients running
503 if os
.access(confFile
.get_opt('WPA.pidfile'), os
.R_OK
):
505 print "Killing existing WPA_SUPPLICANT..."
507 if not confFile
.get_opt('WPA.kill_command') == '':
508 os
.spawnlp(os
.P_WAIT
, confFile
.get_opt('WPA.kill_command'), confFile
.get_opt('WPA.kill_command'))
509 os
.kill(int(open(confFile
.get_opt('WPA.pidfile'), mode
='r').readline()), signal
.SIGTERM
)
511 print "Stale pid file. Removing"
512 os
.remove(confFile
.get_opt('WPA.pidfile'))
513 if os
.path
.isfile(confFile
.get_opt('WPA.pidfile')):
514 print "Stale pid file. Removing"
515 os
.remove(confFile
.get_opt('WPA.pidfile'))
516 # Lets clear out the wireless stuff
518 print "Let's clear out the wireless stuff"
519 os
.spawnlp(os
.P_WAIT
, 'iwconfig', confFile
.get_opt('DEFAULT.iwconfig_command'), confFile
.get_opt('DEFAULT.interface'), 'essid', 'off')
520 os
.spawnlp(os
.P_WAIT
, 'iwconfig', confFile
.get_opt('DEFAULT.iwconfig_command'), confFile
.get_opt('DEFAULT.interface'), 'key', 'off')
521 os
.spawnlp(os
.P_WAIT
, 'iwconfig', confFile
.get_opt('DEFAULT.iwconfig_command'), confFile
.get_opt('DEFAULT.interface'), 'mode', 'auto')
522 os
.spawnlp(os
.P_WAIT
, 'iwconfig', confFile
.get_opt('DEFAULT.iwconfig_command'), confFile
.get_opt('DEFAULT.interface'), 'channel', 'auto')
523 os
.spawnlp(os
.P_WAIT
, 'iwconfig', confFile
.get_opt('DEFAULT.iwconfig_command'), confFile
.get_opt('DEFAULT.interface'), 'ap', 'off')
524 # Now take the interface down
526 print 'Now take the interface down'
527 os
.spawnlp(os
.P_WAIT
, 'ifconfig', confFile
.get_opt('DEFAULT.ifconfig_command'), confFile
.get_opt('DEFAULT.interface'), 'down')
528 # Since it may be brought back up by the next scan, let's unset it's IP
530 print 'Since it may be brought back up by the next scan, lets unset its IP'
531 os
.spawnlp(os
.P_WAIT
, 'ifconfig', confFile
.get_opt('DEFAULT.ifconfig_command'), confFile
.get_opt('DEFAULT.interface'), '0.0.0.0')
532 # Let's run the disconnection postscript
533 dis_postscript
= profile
['dis_postscript']
534 if dis_postscript
.strip() != '':
535 # got something to execute
537 print "executing disconnection postscript:", dis_postscript
538 os
.system(dis_postscript
)
540 print 'Disconnect complete.'
542 def get_profile_from_conf_file( essid
, bssid
):
543 global config_options
544 # We got the essid, get the key
546 section_name
= make_section_name( essid
, bssid
)
547 if not confFile
.has_section( section_name
):
549 profile
['essid'] = essid
550 profile
['bssid'] = bssid
553 profile
['security'] = ''
554 profile
['con_prescript']= ''
555 profile
['con_postscript']= ''
556 profile
['dis_prescript']= ''
557 profile
['dis_postscript']= ''
558 profile
['channel'] = ''
559 profile
['signal'] = '0'
560 profile
['protocol'] = 'b'
562 #if confFile.has_option( section_name, "bssid" ):
563 #possible_bssid = confFile.get( section_name, "bssid" )
564 #if bssid == possible_bssid:
565 #profile['bssid'] = possible_bssid
569 if confFile
.has_option( section_name
, "key" ):
570 profile
['key'] = confFile
.get( section_name
, "key" )
571 if confFile
.has_option( section_name
, "mode" ):
572 profile
['mode'] = confFile
.get( section_name
, "mode" )
573 if confFile
.has_option( section_name
, "security" ):
574 profile
['security'] = confFile
.get( section_name
, "security" )
575 if confFile
.has_option( section_name
, "con_prescript" ):
576 profile
['con_prescript']= confFile
.get( section_name
, "con_prescript" )
577 if confFile
.has_option( section_name
, "con_postscript" ):
578 profile
['con_postscript']= confFile
.get( section_name
, "con_postscript" )
579 if confFile
.has_option( section_name
, "dis_prescript" ):
580 profile
['dis_prescript']= confFile
.get( section_name
, "dis_prescript" )
581 if confFile
.has_option( section_name
, "dis_postscript" ):
582 profile
['dis_postscript']= confFile
.get( section_name
, "dis_postscript" )
583 if confFile
.has_option( section_name
, "channel" ):
584 profile
['channel'] = confFile
.get( section_name
, "channel" )
586 profile
['use_wpa'] = False
587 if confFile
.has_option( section_name
, "use_wpa" ):
588 profile
['use_wpa'] = confFile
.getboolean( section_name
, "use_wpa" )
589 profile
['wpa_driver'] = ''
590 if confFile
.has_option( section_name
, "wpa_driver" ):
591 profile
['wpa_driver'] = confFile
.get( section_name
, "wpa_driver" )
592 profile
['use_dhcp'] = False
593 if confFile
.has_option( section_name
, "use_dhcp" ):
594 profile
['use_dhcp'] = confFile
.getboolean( section_name
, "use_dhcp" )
596 if confFile
.has_option( section_name
, "ip" ):
597 profile
['ip'] = confFile
.get( section_name
, "ip" )
598 profile
['netmask'] = ''
599 if confFile
.has_option( section_name
, "netmask" ):
600 profile
['netmask'] = confFile
.get( section_name
, "netmask" )
601 profile
['gateway'] = ''
602 if confFile
.has_option( section_name
, "gateway" ):
603 profile
['gateway'] = confFile
.get( section_name
, "gateway" )
604 profile
['domain'] = ''
605 if confFile
.has_option( section_name
, "domain" ):
606 profile
['domain'] = confFile
.get( section_name
, "domain" )
608 if confFile
.has_option( section_name
, "dns1" ):
609 profile
['dns1'] = confFile
.get( section_name
, "dns1" )
611 if confFile
.has_option( section_name
, "dns2" ):
612 profile
['dns2'] = confFile
.get( section_name
, "dns2" )
615 def set_profile_to_conf_file( profile
):
616 section_name
= make_section_name( profile
['essid'], profile
['bssid'] )
617 if not confFile
.has_section( section_name
):
618 confFile
.add_section( section_name
)
619 #confFile.set( section_name, 'essid', profile['essid'] )
620 #confFile.set( section_name, 'bssid', profile['bssid'] )
621 confFile
.set( section_name
, 'key', profile
['key'] )
622 confFile
.set( section_name
, 'security', profile
['security'] )
623 confFile
.set( section_name
, 'con_prescript', profile
['con_prescript'] )
624 confFile
.set( section_name
, 'con_postscript', profile
['con_postscript'] )
625 confFile
.set( section_name
, 'dis_prescript', profile
['dis_prescript'] )
626 confFile
.set( section_name
, 'dis_postscript', profile
['dis_postscript'] )
627 confFile
.set( section_name
, 'mode', profile
['mode'] )
628 confFile
.set( section_name
, 'channel', profile
['channel'] )
630 if profile
['use_wpa']:
631 confFile
.set( section_name
, 'use_wpa', 'yes' )
632 confFile
.set( section_name
, 'wpa_driver', profile
['wpa_driver'] )
634 confFile
.set( section_name
, 'use_wpa', 'no' )
636 if profile
['use_dhcp']:
637 confFile
.set( section_name
, 'use_dhcp', 'yes' )
638 try: confFile
.remove_option( section_name
, 'ip' )
640 try: confFile
.remove_option( section_name
, 'netmask' )
642 try: confFile
.remove_option( section_name
, 'gateway' )
644 try: confFile
.remove_option( section_name
, 'domain' )
646 try: confFile
.remove_option( section_name
, 'dns1' )
648 try: confFile
.remove_option( section_name
, 'dns2' )
651 confFile
.set( section_name
, 'use_dhcp', 'no' )
652 confFile
.set( section_name
, 'ip', profile
['ip'] )
653 confFile
.set( section_name
, 'netmask', profile
['netmask'] )
654 confFile
.set( section_name
, 'gateway', profile
['gateway'] )
655 confFile
.set( section_name
, 'domain', profile
['domain'] )
656 confFile
.set( section_name
, 'dns1', profile
['dns1'] )
657 confFile
.set( section_name
, 'dns2', profile
['dns2'] )
660 def make_section_name( essid
, bssid
):
661 return essid
+ ':' + bssid
663 def split_section_name( section
):
664 parts
= re
.split(':', section
)
665 return [ ':'.join(parts
[0:len(parts
)-6]), ':'.join(parts
[len(parts
)-6:len(parts
)]) ]
667 def convert_confFile():
668 for apname
in confFile
.sections():
669 if confFile
.has_option( apname
, 'prescript' ):
670 confFile
.set( apname
, 'con_prescript', confFile
.get( apname
, 'prescript' ) )
671 confFile
.remove_option( apname
, 'prescript' )
672 if confFile
.has_option( apname
, 'postscript' ):
673 confFile
.set( apname
, 'con_postscript', confFile
.get( apname
, 'postscript' ) )
674 confFile
.remove_option( apname
, 'postscript' )
675 confFile
.set( apname
, 'dis_prescript', '' )
676 confFile
.set( apname
, 'dis_postscript', '' )
682 def __init__( self
, confFile
):
683 # create the main window and connect the normal events
684 global signal_xpm_none
685 global signal_xpm_low
686 global signal_xpm_barely
688 global signal_xpm_best
689 global known_profile_icon
690 global unknown_profile_icon
691 global wifi_radar_icon
692 self
.signal_none_pb
= gtk
.gdk
.pixbuf_new_from_xpm_data( signal_xpm_none
)
693 self
.known_profile_icon
= gtk
.gdk
.pixbuf_new_from_inline( len( known_profile_icon
[0] ), known_profile_icon
[0], False )
694 self
.unknown_profile_icon
= gtk
.gdk
.pixbuf_new_from_inline( len( unknown_profile_icon
[0] ), unknown_profile_icon
[0], False )
695 self
.signal_low_pb
= gtk
.gdk
.pixbuf_new_from_xpm_data( signal_xpm_low
)
696 self
.signal_barely_pb
= gtk
.gdk
.pixbuf_new_from_xpm_data( signal_xpm_barely
)
697 self
.signal_ok_pb
= gtk
.gdk
.pixbuf_new_from_xpm_data( signal_xpm_ok
)
698 self
.signal_best_pb
= gtk
.gdk
.pixbuf_new_from_xpm_data( signal_xpm_best
)
699 self
.window
= gtk
.Dialog('WiFi Radar', None, gtk
.DIALOG_MODAL
)
700 icon
= gtk
.gdk
.pixbuf_new_from_inline( len( wifi_radar_icon
[0] ), wifi_radar_icon
[0], False )
701 self
.window
.set_icon( icon
)
702 self
.window
.set_border_width( 10 )
703 self
.window
.set_size_request( 720, 300 )
704 self
.window
.set_title( "WiFi Radar" )
705 self
.window
.connect( 'delete_event', self
.delete_event
)
706 self
.window
.connect( 'destroy', self
.destroy
, )
707 # let's create all our widgets
708 self
.current_network
= gtk
.Label()
709 self
.current_network
.show()
710 self
.close_button
= gtk
.Button( "Close", gtk
.STOCK_CLOSE
)
711 self
.close_button
.show()
712 self
.close_button
.connect( 'clicked', self
.delete_event
, None )
713 self
.preferences_button
= gtk
.Button( "Preferences", gtk
.STOCK_PREFERENCES
)
714 self
.preferences_button
.show()
715 self
.preferences_button
.connect( 'clicked', self
.edit_preferences
, None )
716 # essid bssid known_icon known available wep_icon signal_level mode protocol channel
717 self
.pstore
= gtk
.ListStore( str, str, gtk
.gdk
.Pixbuf
, int, int, str, gtk
.gdk
.Pixbuf
, str, str, str )
718 self
.rebuild_plist_items()
719 self
.plist
= gtk
.TreeView( self
.pstore
)
721 self
.pix_cell
= gtk
.CellRendererPixbuf()
722 self
.wep_cell
= gtk
.CellRendererPixbuf()
723 self
.essid_cell
= gtk
.CellRendererText()
724 self
.bssid_cell
= gtk
.CellRendererText()
725 self
.bssid_cell
.set_property("width-chars", 20)
726 self
.pcol
= gtk
.TreeViewColumn( "SSID" )
727 self
.pcol
.pack_start( self
.pix_cell
, False )
728 self
.pcol
.pack_start( self
.wep_cell
, False )
729 self
.pcol
.pack_start( self
.essid_cell
, True )
730 self
.pcol
.pack_start( self
.bssid_cell
, True )
731 self
.pcol
.add_attribute( self
.wep_cell
, 'stock-id', 5 )
732 self
.pcol
.add_attribute( self
.pix_cell
, 'pixbuf', 2 )
733 self
.pcol
.add_attribute( self
.essid_cell
, 'text', 0 )
734 self
.pcol
.add_attribute( self
.bssid_cell
, 'text', 1 )
735 self
.plist
.append_column( self
.pcol
)
737 self
.sig_cell
= gtk
.CellRendererPixbuf()
738 self
.scol
= gtk
.TreeViewColumn( "Signal" )
739 self
.scol
.pack_start( self
.sig_cell
, True )
740 self
.scol
.add_attribute( self
.sig_cell
, 'pixbuf', 6 )
741 self
.plist
.append_column( self
.scol
)
743 self
.mode_cell
= gtk
.CellRendererText()
744 self
.mcol
= gtk
.TreeViewColumn( "Mode" )
745 self
.mcol
.pack_start( self
.mode_cell
, True )
746 self
.mcol
.add_attribute( self
.mode_cell
, 'text', 7 )
747 self
.plist
.append_column( self
.mcol
)
748 # The protocol column
749 self
.prot_cell
= gtk
.CellRendererText()
750 self
.protcol
= gtk
.TreeViewColumn( "802.11" )
751 self
.protcol
.pack_start( self
.prot_cell
, True )
752 self
.protcol
.add_attribute( self
.prot_cell
, 'text', 8 )
753 self
.plist
.append_column( self
.protcol
)
755 self
.channel_cell
= gtk
.CellRendererText()
756 self
.channel
= gtk
.TreeViewColumn( "Channel" )
757 self
.channel
.pack_start( self
.channel_cell
, True )
758 self
.channel
.add_attribute( self
.channel_cell
, 'text', 9 )
759 self
.plist
.append_column( self
.channel
)
761 self
.plist
.set_reorderable( True )
762 self
.pstore
.connect( 'row-changed', self
.update_auto_profile_order
)
763 # enable/disable buttons based on the selected network
764 self
.selected_network
= self
.plist
.get_selection()
765 self
.selected_network
.connect( 'changed', self
.on_network_selection
, None )
766 # the list scroll bar
767 sb
= gtk
.VScrollbar( self
.plist
.get_vadjustment() )
771 self
.new_button
= gtk
.Button( "_New" )
772 self
.new_button
.connect( 'clicked', self
.create_new_profile
, None )
773 self
.new_button
.show()
775 self
.edit_button
= gtk
.Button( "C_onfigure" )
776 self
.edit_button
.connect( 'clicked', self
.edit_profile
, None )
777 self
.edit_button
.show()
779 self
.delete_button
= gtk
.Button( "_Delete" )
780 self
.delete_button
.connect( 'clicked', self
.delete_profile
, None )
781 self
.delete_button
.show()
783 self
.connect_button
= gtk
.Button( "Co_nnect" )
784 self
.connect_button
.connect( 'clicked', self
.connect_profile
, None )
786 self
.disconnect_button
= gtk
.Button( "D_isconnect" )
787 self
.disconnect_button
.connect( 'clicked', self
.disconnect_profile
, None )
788 # lets add our widgets
789 rows
= gtk
.VBox( False, 3 )
790 net_list
= gtk
.HBox( False, 0 )
791 listcols
= gtk
.HBox( False, 0 )
792 prows
= gtk
.VBox( False, 0 )
795 net_list
.pack_start( self
.plist
, True, True, 0 )
796 net_list
.pack_start( sb
, False, False, 0 )
798 rows
.pack_start( net_list
, True, True, 0 )
799 rows
.pack_start( self
.current_network
, False, True, 0 )
801 listcols
.pack_start( rows
, True, True, 0 )
802 listcols
.pack_start( prows
, False, False, 5 )
804 prows
.pack_start( self
.new_button
, False, False, 2 )
805 prows
.pack_start( self
.edit_button
, False, False, 2 )
806 prows
.pack_start( self
.delete_button
, False, False, 2 )
807 prows
.pack_end( self
.connect_button
, False, False, 2 )
808 prows
.pack_end( self
.disconnect_button
, False, False, 2 )
810 self
.window
.action_area
.pack_start( self
.preferences_button
)
811 self
.window
.action_area
.pack_start( self
.close_button
)
816 self
.window
.vbox
.add( listcols
)
817 self
.window
.vbox
.set_spacing( 3 )
818 self
.window
.show_all()
820 # Now, immediately hide these two. The proper one will be
821 # displayed later, based on interface state. -BEF-
822 self
.disconnect_button
.hide()
823 self
.connect_button
.hide()
828 def destroy( self
, widget
= None):
835 def delete_event( self
, widget
, event
, data
=None ):
836 # Save the preferred networks order
839 self
.update_auto_profile_order()
843 def rebuild_plist_items( self
):
844 # Add our known profiles in order
849 #print "rebuild_plist_items (1): ", confFile.auto_profile_order
850 for ap
in confFile
.auto_profile_order
:
852 if access_points
.has_key( ap
) and access_points
[ ap
]['known']:
854 if access_points
[ ap
]['encrypted']: wep
= gtk
.STOCK_DIALOG_AUTHENTICATION
855 # 1 here means that we know this ap -----------------------------------------------------------------------v
856 self
.pstore
.append( [ access_points
[ ap
]['essid'], access_points
[ ap
]['bssid'], self
.known_profile_icon
, 1, 0, wep
, self
.signal_none_pb
, access_points
[ ap
]['mode'], access_points
[ ap
]['protocol'], access_points
[ ap
]['channel'] ] )
857 # Now add any known profiles not in the profile order
858 for ap
in access_points
:
859 #print "rebuild_plist_items (2): ", ap, ":", confFile.auto_profile_order
860 if ap
in confFile
.auto_profile_order
: continue
862 if access_points
[ ap
]['encrypted']: wep
= gtk
.STOCK_DIALOG_AUTHENTICATION
863 # 1 here means that we know this ap -------------------------------------------------------------------------v
864 self
.pstore
.append( [ access_points
[ ap
]['essid'], access_points
[ ap
]['bssid'], self
.unknown_profile_icon
, 0, 0, wep
, self
.signal_none_pb
, access_points
[ ap
]['mode'], access_points
[ ap
]['protocol'], access_points
[ ap
]['channel'] ] )
868 def update_plist_items( self
):
869 """Updates the profiles list"""
872 # print "updating profile list"
873 gtk
.gdk
.threads_enter()
877 # update the current ip and essid
878 self
.current_network
.set_text( "Connected to %s ip(%s)" % ( get_current_essid(), get_current_ip() ) )
880 self
.connect_button
.hide()
881 self
.disconnect_button
.show()
883 self
.disconnect_button
.hide()
884 self
.connect_button
.show()
886 for ap
in access_points
:
888 if access_points
[ ap
]['encrypted']: wep
= gtk
.STOCK_DIALOG_AUTHENTICATION
889 prow
= self
.get_row_by_ap( access_points
[ ap
][ 'essid' ], access_points
[ ap
][ 'bssid' ] )
892 # print "Setting prow", ap, access_points[ ap ]
893 #profile = get_profile_from_conf_file( access_points[ ap ][ 'essid' ], access_points[ ap ][ 'bssid' ] )
895 prow
[1] = access_points
[ ap
][ 'bssid' ]
897 prow
[6] = self
.pixbuf_from_signal( access_points
[ ap
][ 'signal' ] )
898 prow
[7] = access_points
[ ap
][ 'mode' ]
899 prow
[8] = access_points
[ ap
][ 'protocol' ]
900 prow
[9] = access_points
[ ap
]['channel']
905 # print "New profile", ap, access_points[ ap ]
906 # 1 here means that we know this ap ---------------------------------------------------------------------------v
907 self
.pstore
.append( [ access_points
[ ap
][ 'essid' ], access_points
[ ap
]['bssid'], self
.unknown_profile_icon
, 0, 0, wep
, self
.pixbuf_from_signal( access_points
[ ap
]['signal'] ), access_points
[ ap
]['mode'], access_points
[ ap
]['protocol'], access_points
[ ap
]['channel'] ] )
908 # give the list a chance to update
909 #while gtk.events_pending():
910 # gtk.main_iteration()
914 gtk
.gdk
.threads_leave()
917 def pixbuf_from_signal( self
, signal
):
918 signal
= int( signal
)
920 if signal
>= 80 or signal
== 0:
921 return self
.signal_none_pb
923 return self
.signal_low_pb
925 return self
.signal_barely_pb
927 return self
.signal_ok_pb
929 return self
.signal_best_pb
933 def get_row_by_ap( self
, essid
, bssid
):
934 for row
in self
.pstore
:
935 if ( (row
[0] == essid
) and (row
[1] == bssid
) ):
940 # enable/disable buttons based on the selected network
941 def on_network_selection( self
, widget
, data
=None ):
942 ( store
, selected_iter
) = self
.selected_network
.get_selected()
944 # if no networks are selected, disable all buttons except New
945 # (this occurs after a drag-and-drop)
946 if selected_iter
==None:
947 self
.new_button
.set_sensitive(True)
948 self
.edit_button
.set_sensitive(False)
949 self
.delete_button
.set_sensitive(False)
952 # determine if the selected network is configured
953 is_configured
= (store
.get_value(selected_iter
, 2) == 1)
955 # enable/disable buttons
957 self
.new_button
.set_sensitive(False)
958 self
.edit_button
.set_sensitive(True)
959 self
.delete_button
.set_sensitive(True)
961 self
.new_button
.set_sensitive(True)
962 self
.edit_button
.set_sensitive(True)
963 self
.delete_button
.set_sensitive(False)
967 # init and run the preferences dialog
968 def edit_preferences( self
, widget
, data
=None ):
969 p
= preferences_dialog( self
)
973 def create_new_profile( self
, widget
, data
=None ):
975 p
= profile_dialog( self
)
979 profile
= p
.get_profile()
980 # Check that the ap does not exist already
981 apname
= make_section_name( profile
['essid'], profile
['bssid'] )
982 if apname
in access_points
:
983 dlg
= gtk
.MessageDialog(
985 gtk
.DIALOG_DESTROY_WITH_PARENT | gtk
.DIALOG_MODAL
,
988 "A profile for %s already exists" % (apname
) )
994 set_profile_to_conf_file( profile
)
995 # And let's add it up
998 ap
['available'] = False
999 ap
['encrypted'] = False
1004 ap
['con_prescript'] = ''
1005 ap
['con_postscript'] = ''
1006 ap
['dis_prescript'] = ''
1007 ap
['dis_postscript'] = ''
1009 ap
['protocol'] = 'b'
1011 if confFile
.has_option( apname
, 'key'):
1012 if len( confFile
.get( apname
, 'key' ) ) > 0:
1013 ap
['encrypted'] = True
1017 access_points
[ apname
] = ap
1018 # if it is not in the auto_profile_order add it
1019 #print "create_new_profile: ", apname, ":", confFile.auto_profile_order
1020 if not apname
in confFile
.auto_profile_order
:
1021 confFile
.auto_profile_order
.append(apname
)
1025 if ap
['encrypted']: wep
= gtk
.STOCK_DIALOG_AUTHENTICATION
1026 self
.pstore
.append( [ profile
['essid'], profile
['bssid'], self
.known_profile_icon
, 1, 0, wep
, self
.pixbuf_from_signal( ap
['signal'] ), ap
['mode'], ap
['protocol'] ] )
1030 def edit_profile( self
, widget
, data
=None ):
1031 ( store
, selected_iter
) = self
.plist
.get_selection().get_selected()
1032 if not selected_iter
: return
1033 essid
= store
.get_value( selected_iter
, 0 )
1034 bssid
= store
.get_value( selected_iter
, 1 )
1035 known
= store
.get_value( selected_iter
, 3 )
1037 self
.connect_profile(widget
, 'noconnect')
1039 profile
= get_profile_from_conf_file( essid
, bssid
)
1040 p
= profile_dialog( self
)
1041 p
.set_profile( profile
, True )
1044 profile
= p
.get_profile()
1046 print "Got edited profile ", profile
1047 set_profile_to_conf_file( profile
)
1050 def delete_profile( self
, widget
, data
=None ):
1051 ( store
, selected_iter
) = self
.plist
.get_selection().get_selected()
1052 if not selected_iter
: return
1053 essid
= store
.get_value( selected_iter
, 0 )
1054 bssid
= store
.get_value( selected_iter
, 1 )
1055 known
= store
.get_value( selected_iter
, 3 )
1056 if not known
: return
1057 dlg
= gtk
.MessageDialog(
1059 gtk
.DIALOG_DESTROY_WITH_PARENT | gtk
.DIALOG_MODAL
,
1060 gtk
.MESSAGE_QUESTION
,
1062 "Are you sure you want to delete the %s (%s) profile?" % (essid
, bssid
) )
1066 if res
== gtk
.RESPONSE_NO
: return
1068 apname
= make_section_name( essid
, bssid
)
1069 confFile
.remove_section( apname
)
1070 #print "delete_profile: ", apname, ":", confFile.auto_profile_order
1071 if apname
in confFile
.auto_profile_order
: confFile
.auto_profile_order
.remove(apname
)
1072 if access_points
.has_key( apname
): access_points
.pop( apname
)
1073 self
.pstore
.remove( selected_iter
)
1074 # Let's save our current state
1075 self
.update_auto_profile_order()
1077 def connect_profile( self
, widget
, data
=None ):
1078 ( store
, selected_iter
) = self
.plist
.get_selection().get_selected()
1079 if not selected_iter
: return
1080 essid
= store
.get_value( selected_iter
, 0 )
1081 bssid
= store
.get_value( selected_iter
, 1 )
1082 known
= store
.get_value( selected_iter
, 3 )
1084 if data
!= 'noconnect':
1085 dlg
= gtk
.MessageDialog(
1087 gtk
.DIALOG_DESTROY_WITH_PARENT | gtk
.DIALOG_MODAL
,
1088 gtk
.MESSAGE_QUESTION
,
1090 "This network does not have a profile configured.\n\nWould you like to create one now?" )
1094 if res
== gtk
.RESPONSE_NO
: return
1095 p
= profile_dialog( self
)
1096 # get a blank profile from the dialog
1097 profile
= p
.get_profile()
1098 profile
['essid'] = essid
1099 profile
['bssid'] = bssid
1100 p
.set_profile( profile
, True )
1103 profile
= p
.get_profile()
1104 set_profile_to_conf_file( profile
)
1106 self
.pstore
.set_value( selected_iter
, 2, self
.known_profile_icon
)
1108 self
.pstore
.set_value( selected_iter
, 3, 1 )
1109 # if it is not in the auto_profile_order add it
1110 apname
= make_section_name( essid
, bssid
)
1111 #print "connect_profile: ", apname, ":", confFile.auto_profile_order
1112 if not apname
in confFile
.auto_profile_order
:
1113 confFile
.auto_profile_order
.append( apname
)
1114 self
.update_auto_profile_order()
1119 if data
!= 'noconnect':
1120 connect_status_window
= status_window( self
)
1121 connect_status_window
.run()
1122 connect_to_network( essid
, bssid
, connect_status_window
)
1123 connect_status_window
.destroy()
1125 def disconnect_profile( self
, widget
, data
=None ):
1126 disconnect_interface()
1128 def update_auto_profile_order( self
, widget
= None, data
= None, data2
= None ):
1129 # recreate the auto_profile_order
1130 auto_profile_order
= []
1131 piter
= self
.pstore
.get_iter_first()
1133 # only if it's known
1134 if self
.pstore
.get_value( piter
, 3 ) == 1:
1135 auto_profile_order
.append( make_section_name( self
.pstore
.get_value( piter
, 0 ), self
.pstore
.get_value( piter
, 1 ) ) )
1136 piter
= self
.pstore
.iter_next( piter
)
1137 confFile
.auto_profile_order
= auto_profile_order
1139 ###################################
1140 # the preferences dialog
1141 class preferences_dialog
:
1142 def __init__( self
, parent
):
1143 # set up the preferences window
1144 global wifi_radar_icon
1145 self
.parent
= parent
1146 self
.dialog
= gtk
.Dialog('WiFi Radar Preferences', self
.parent
.window
,
1147 gtk
.DIALOG_MODAL | gtk
.DIALOG_DESTROY_WITH_PARENT
,
1148 ( gtk
.STOCK_CLOSE
, True ) )
1149 icon
= gtk
.gdk
.pixbuf_new_from_inline( len( wifi_radar_icon
[0] ), wifi_radar_icon
[0], False )
1150 self
.dialog
.set_icon( icon
)
1151 self
.dialog
.set_resizable( True )
1152 self
.dialog
.set_transient_for( self
.parent
.window
)
1153 self
.tooltips
= gtk
.Tooltips()
1156 # set up preferences widgets
1159 # auto detect wireless device
1160 self
.w_auto_detect
= gtk
.CheckButton("Auto-detect wireless device")
1161 self
.w_auto_detect
.set_active(confFile
.get_opt('DEFAULT.interface') == "auto_detect")
1162 self
.w_auto_detect
.connect("toggled", self
.toggle_auto_detect
)
1163 self
.tooltips
.set_tip(self
.w_auto_detect
, "Automatically select wireless device to configure")
1164 self
.dialog
.vbox
.pack_start(self
.w_auto_detect
, False, False, 5)
1165 # network interface selecter
1166 self
.w_interface
= gtk
.combo_box_entry_new_text()
1167 iwconfig_info
= os
.popen(confFile
.get_opt('DEFAULT.iwconfig_command') + " 2>&1", 'r')
1168 wireless_devices
= [ (x
[0:x
.find(" ")]) for x
in iwconfig_info
if("ESSID" in x
)]
1169 for device
in wireless_devices
:
1170 if device
!= confFile
.get_opt('DEFAULT.interface'):
1171 self
.w_interface
.append_text(device
)
1172 self
.w_interface
.prepend_text(confFile
.get_opt('DEFAULT.interface'))
1173 self
.w_interface
.set_active(0)
1174 self
.w_interface_label
= gtk
.Label("Wireless device")
1175 self
.w_hbox1
= gtk
.HBox(False, 0)
1176 self
.w_hbox1
.pack_start(self
.w_interface_label
, False, False, 5)
1177 self
.w_hbox1
.pack_start(self
.w_interface
, True, True, 0)
1178 self
.w_interface
.set_sensitive(confFile
.get_opt('DEFAULT.interface') != "auto_detect")
1179 self
.dialog
.vbox
.pack_start(self
.w_hbox1
, False, False, 5)
1180 # scan timeout (spin button of integers from 1 to 100)
1181 self
.time_in_seconds
= gtk
.Adjustment(confFile
.get_opt_as_int('DEFAULT.scan_timeout'),1,100,1,1,1)
1182 self
.w_scan_timeout
= gtk
.SpinButton(self
.time_in_seconds
, 1, 0)
1183 self
.w_scan_timeout
.set_update_policy(gtk
.UPDATE_IF_VALID
)
1184 self
.w_scan_timeout
.set_numeric(True)
1185 self
.w_scan_timeout
.set_snap_to_ticks(True)
1186 self
.w_scan_timeout
.set_wrap(False)
1187 self
.tooltips
.set_tip(self
.w_scan_timeout
, "How long should WiFi Radar scan for access points?")
1188 self
.w_scan_timeout_label
= gtk
.Label("Scan timeout (seconds)")
1189 self
.w_hbox2
= gtk
.HBox(False, 0)
1190 self
.w_hbox2
.pack_start(self
.w_scan_timeout_label
, False, False, 5)
1191 self
.w_hbox2
.pack_start(self
.w_scan_timeout
, True, True, 0)
1192 self
.dialog
.vbox
.pack_start(self
.w_hbox2
, False, False, 5)
1194 self
.w_speak_up
= gtk
.CheckButton("Use speak-up")
1195 self
.w_speak_up
.set_active(confFile
.get_opt_as_bool('DEFAULT.speak_up'))
1196 self
.tooltips
.set_tip(self
.w_speak_up
, "Should I speak up when connecting to a network? (If you have a speech command)")
1197 self
.dialog
.vbox
.pack_start(self
.w_speak_up
, False, False, 5)
1199 self
.w_commit_required
= gtk
.CheckButton("Commit required")
1200 self
.w_commit_required
.set_active(confFile
.get_opt_as_bool('DEFAULT.commit_required'))
1201 self
.tooltips
.set_tip(self
.w_commit_required
, "Check this box if your card requires a \"commit\" command with iwconfig")
1202 self
.dialog
.vbox
.pack_start(self
.w_commit_required
, False, False, 5)
1204 self
.w_ifup_required
= gtk
.CheckButton("Ifup required")
1205 self
.w_ifup_required
.set_active(confFile
.get_opt_as_bool('DEFAULT.ifup_required'))
1206 self
.tooltips
.set_tip(self
.w_ifup_required
, "Check this box if your system requires the interface to be brought up first")
1208 self
.dialog
.vbox
.pack_start(self
.w_ifup_required
, False, False, 5)
1210 def toggle_auto_detect(self
, auto_detect_toggle
, data
=None):
1211 self
.w_interface
.set_sensitive(not auto_detect_toggle
.get_active())
1214 self
.dialog
.show_all()
1215 return self
.dialog
.run()
1218 # save preferences to config file
1219 if self
.w_auto_detect
.get_active():
1220 set_network_device("auto_detect")
1221 confFile
.set_opt('DEFAULT.interface', "auto_detect")
1223 set_network_device(self
.w_interface
.child
.get_text())
1224 confFile
.set_opt('DEFAULT.interface', self
.w_interface
.child
.get_text())
1225 # reconfigure the dhcp commands in case the network device was changed
1226 confFile
.set_float_opt('DEFAULT.scan_timeout', self
.w_scan_timeout
.get_value())
1227 confFile
.set_bool_opt('DEFAULT.speak_up', self
.w_speak_up
.get_active())
1228 confFile
.set_bool_opt('DEFAULT.commit_required', self
.w_commit_required
.get_active())
1229 confFile
.set_bool_opt('DEFAULT.ifup_required', self
.w_ifup_required
.get_active())
1230 if confFile
.get_opt_as_bool('DEFAULT.ifup_required'):
1231 os
.spawnlp(os
.P_WAIT
, 'ifconfig', confFile
.get_opt('DEFAULT.ifconfig_command'), confFile
.get_opt('DEFAULT.interface'), "up")
1233 self
.dialog
.destroy()
1237 ###################################
1238 class profile_dialog
:
1239 def __init__( self
, parent
):
1240 global wifi_radar_icon
1241 self
.parent
= parent
1242 self
.dialog
= gtk
.Dialog('WiFi Profile', self
.parent
.window
,
1243 gtk
.DIALOG_MODAL | gtk
.DIALOG_DESTROY_WITH_PARENT
,
1244 ( gtk
.STOCK_CANCEL
, False, gtk
.STOCK_SAVE
, True ) )
1245 icon
= gtk
.gdk
.pixbuf_new_from_inline( len( wifi_radar_icon
[0] ), wifi_radar_icon
[0], False )
1246 self
.dialog
.set_icon( icon
)
1247 self
.dialog
.set_resizable( False )
1248 self
.dialog
.set_transient_for( self
.parent
.window
)
1249 #self.dialog.set_size_request( 400, 400 )
1251 essid_table
= gtk
.Table( 1, 2, False )
1252 essid_table
.set_row_spacings( 3 )
1253 essid_table
.set_col_spacings( 3 )
1256 l
= gtk
.Label( 'Network Name' )
1257 essid_table
.attach( l
, 0, 1, 0, 1 )
1258 # The essid textboxes
1259 self
.essid
= gtk
.Entry( 32 )
1260 self
.essid
.set_text('essid')
1261 essid_table
.attach( self
.essid
, 1, 2, 0, 1 )
1262 #self.key = gtk.Entry( 32 )
1263 #essid_table.attach( self.key, 1, 2, 1, 2 )
1264 # Add the essid table to the dialog
1265 self
.dialog
.vbox
.pack_start( essid_table
, True, True, 5 )
1267 bssid_table
= gtk
.Table( 1, 2, False )
1268 bssid_table
.set_row_spacings( 3 )
1269 bssid_table
.set_col_spacings( 3 )
1271 l
= gtk
.Label( 'Network bssid' )
1272 bssid_table
.attach( l
, 0, 1, 0, 1 )
1273 # The bssid textboxes
1274 self
.bssid
= gtk
.Entry( 32 )
1275 self
.bssid
.set_text('')
1276 bssid_table
.attach( self
.bssid
, 1, 2, 0, 1 )
1277 #self.key = gtk.Entry( 32 )
1278 #bssid_table.attach( self.key, 1, 2, 1, 2 )
1279 # Add the bssid table to the dialog
1280 self
.dialog
.vbox
.pack_start( bssid_table
, True, True, 5 )
1282 # create the wifi expander
1283 self
.wifi_expander
= gtk
.Expander( WIFI_SET_LABEL
)
1284 #self.wifi_expander.connect( 'notify::expanded', self.toggle_use_dhcp )
1285 wifi_table
= gtk
.Table( 4, 2, False )
1286 wifi_table
.set_row_spacings( 3 )
1287 wifi_table
.set_col_spacings( 3 )
1289 l
= gtk
.Label( 'Mode' )
1290 wifi_table
.attach( l
, 0, 1, 0, 1 )
1291 l
= gtk
.Label( 'Channel' )
1292 wifi_table
.attach( l
, 0, 1, 1, 2 )
1293 l
= gtk
.Label( 'Key' )
1294 wifi_table
.attach( l
, 0, 1, 2, 3 )
1295 l
= gtk
.Label( 'Security' )
1296 wifi_table
.attach( l
, 0, 1, 3, 4 )
1297 # The Wifi text boxes
1298 self
.mode
= gtk
.combo_box_new_text()
1299 for mode
in WIFI_MODES
:
1300 self
.mode
.append_text( mode
)
1301 self
.mode
.set_active( 0 )
1302 wifi_table
.attach( self
.mode
, 1, 2, 0, 1 )
1303 self
.channel
= gtk
.combo_box_new_text()
1304 for channel
in WIFI_CHANNELS
:
1305 self
.channel
.append_text( channel
)
1306 self
.channel
.set_active( 0 )
1307 wifi_table
.attach( self
.channel
, 1, 2, 1, 2 )
1308 self
.key
= gtk
.Entry( 32 )
1309 #self.key.set_text('0.0.0.0')
1310 wifi_table
.attach( self
.key
, 1, 2, 2, 3 )
1311 self
.security
= gtk
.combo_box_new_text()
1312 for security
in WIFI_SECURITY
:
1313 self
.security
.append_text( security
)
1314 self
.security
.set_active( 0 )
1315 wifi_table
.attach( self
.security
, 1, 2, 3, 4 )
1316 # Add the wifi table to the expander
1317 self
.wifi_expander
.add( wifi_table
)
1318 # Add the expander to the dialog
1319 self
.dialog
.vbox
.pack_start( self
.wifi_expander
, False, False, 5 )
1321 # create the wpa expander
1322 self
.wpa_expander
= gtk
.Expander( NO_WPA_LABEL
)
1323 self
.wpa_expander
.connect( 'notify::expanded', self
.toggle_use_wpa
)
1324 wpa_table
= gtk
.Table( 1, 2, False )
1325 wpa_table
.set_row_spacings( 3 )
1326 wpa_table
.set_col_spacings( 3 )
1328 l
= gtk
.Label( 'Driver' )
1329 wpa_table
.attach( l
, 0, 1, 0, 1 )
1331 self
.wpa_driver
= gtk
.Entry()
1332 wpa_table
.attach( self
.wpa_driver
, 1, 2, 0, 1 )
1333 # Add the wpa table to the expander
1334 self
.wpa_expander
.add( wpa_table
)
1335 # Add the expander to the dialog
1336 self
.dialog
.vbox
.pack_start( self
.wpa_expander
, False, False, 5 )
1338 # create the dhcp expander
1339 self
.dhcp_expander
= gtk
.Expander( USE_DHCP_LABEL
)
1340 self
.dhcp_expander
.connect( 'notify::expanded', self
.toggle_use_dhcp
)
1341 ip_table
= gtk
.Table( 6, 2, False )
1342 ip_table
.set_row_spacings( 3 )
1343 ip_table
.set_col_spacings( 3 )
1345 l
= gtk
.Label( 'IP' )
1346 ip_table
.attach( l
, 0, 1, 0, 1 )
1347 l
= gtk
.Label( 'Netmask' )
1348 ip_table
.attach( l
, 0, 1, 1, 2 )
1349 l
= gtk
.Label( 'Gateway' )
1350 ip_table
.attach( l
, 0, 1, 2, 3 )
1351 l
= gtk
.Label( 'Domain' )
1352 ip_table
.attach( l
, 0, 1, 3, 4 )
1353 l
= gtk
.Label( 'DNS' )
1354 ip_table
.attach( l
, 0, 1, 4, 5 )
1355 l
= gtk
.Label( 'DNS' )
1356 ip_table
.attach( l
, 0, 1, 5, 6 )
1358 self
.ip
= gtk
.Entry( 15 )
1359 self
.ip
.set_text('0.0.0.0')
1360 ip_table
.attach( self
.ip
, 1, 2, 0, 1 )
1361 self
.netmask
= gtk
.Entry( 15 )
1362 self
.netmask
.set_text('255.255.255.0')
1363 ip_table
.attach( self
.netmask
, 1, 2, 1, 2 )
1364 self
.gw
= gtk
.Entry( 15 )
1365 self
.gw
.set_text('0.0.0.0')
1366 ip_table
.attach( self
.gw
, 1, 2, 2, 3 )
1367 self
.domain
= gtk
.Entry( 32 )
1368 self
.domain
.set_text('domain.com')
1369 ip_table
.attach( self
.domain
, 1, 2, 3, 4 )
1370 self
.dns1
= gtk
.Entry( 15 )
1371 self
.dns1
.set_text('0.0.0.0')
1372 ip_table
.attach( self
.dns1
, 1, 2, 4, 5 )
1373 self
.dns2
= gtk
.Entry( 15 )
1374 self
.dns2
.set_text('0.0.0.0')
1375 ip_table
.attach( self
.dns2
, 1, 2, 5, 6 )
1376 # Add the ip table to the expander
1377 self
.dhcp_expander
.add( ip_table
)
1378 # Add the expander to the dialog
1379 self
.dialog
.vbox
.pack_start( self
.dhcp_expander
, False, False, 5 )
1381 # create the connection-building postpre expander
1382 self
.con_pp_expander
= gtk
.Expander( CON_PP_LABEL
)
1383 con_pp_table
= gtk
.Table( 2, 2, False )
1384 con_pp_table
.set_row_spacings( 3 )
1385 con_pp_table
.set_col_spacings( 3 )
1387 l
= gtk
.Label( 'Before' )
1388 con_pp_table
.attach( l
, 0, 1, 0, 1 )
1389 l
= gtk
.Label( 'After' )
1390 con_pp_table
.attach( l
, 0, 1, 1, 2 )
1392 self
.con_prescript
= gtk
.Entry()
1393 con_pp_table
.attach( self
.con_prescript
, 1, 2, 0, 1 )
1394 self
.con_postscript
= gtk
.Entry()
1395 con_pp_table
.attach( self
.con_postscript
, 1, 2, 1, 2 )
1396 # Add the pp table to the expander
1397 self
.con_pp_expander
.add( con_pp_table
)
1398 # Add the expander to the dialog
1399 self
.dialog
.vbox
.pack_start( self
.con_pp_expander
, False, False, 5 )
1401 # create the disconnection postpre expander
1402 self
.dis_pp_expander
= gtk
.Expander( DIS_PP_LABEL
)
1403 dis_pp_table
= gtk
.Table( 2, 2, False )
1404 dis_pp_table
.set_row_spacings( 3 )
1405 dis_pp_table
.set_col_spacings( 3 )
1407 l
= gtk
.Label( 'Before' )
1408 dis_pp_table
.attach( l
, 0, 1, 0, 1 )
1409 l
= gtk
.Label( 'After' )
1410 dis_pp_table
.attach( l
, 0, 1, 1, 2 )
1412 self
.dis_prescript
= gtk
.Entry()
1413 dis_pp_table
.attach( self
.dis_prescript
, 1, 2, 0, 1 )
1414 self
.dis_postscript
= gtk
.Entry()
1415 dis_pp_table
.attach( self
.dis_postscript
, 1, 2, 1, 2 )
1416 # Add the pp table to the expander
1417 self
.dis_pp_expander
.add( dis_pp_table
)
1418 # Add the expander to the dialog
1419 self
.dialog
.vbox
.pack_start( self
.dis_pp_expander
, False, False, 5 )
1422 self
.dialog
.show_all()
1423 return self
.dialog
.run()
1425 def destroy( self
):
1426 self
.dialog
.destroy()
1429 def toggle_use_dhcp( self
, widget
, data
= None ):
1430 expanded
= self
.dhcp_expander
.get_expanded()
1432 self
.dhcp_expander
.set_label( USE_IP_LABEL
)
1434 self
.dhcp_expander
.set_label( USE_DHCP_LABEL
)
1436 def toggle_use_wpa( self
, widget
, data
= None ):
1437 expanded
= self
.wpa_expander
.get_expanded()
1439 self
.wpa_expander
.set_label( USE_WPA_LABEL
)
1441 self
.wpa_expander
.set_label( NO_WPA_LABEL
)
1443 def get_profile( self
):
1445 profile
['essid'] = self
.essid
.get_text().strip()
1446 profile
['bssid'] = self
.bssid
.get_text().strip()
1447 profile
['key'] = self
.key
.get_text().strip()
1448 profile
['mode'] = self
.get_array_item( self
.mode
.get_active(), WIFI_MODES
)
1449 profile
['security'] = self
.get_array_item( self
.security
.get_active(), WIFI_SECURITY
)
1450 profile
['channel'] = self
.get_array_item( self
.channel
.get_active(), WIFI_CHANNELS
)
1451 profile
['protocol'] = 'b'
1452 profile
['signal'] = '0'
1453 profile
['con_prescript'] = self
.con_prescript
.get_text().strip()
1454 profile
['con_postscript'] = self
.con_postscript
.get_text().strip()
1455 profile
['dis_prescript'] = self
.dis_prescript
.get_text().strip()
1456 profile
['dis_postscript'] = self
.dis_postscript
.get_text().strip()
1458 use_wpa
= ( self
.wpa_expander
.get_expanded() == False )
1460 profile
['use_wpa'] = False
1462 profile
['use_wpa'] = True
1463 profile
['wpa_driver']= self
.wpa_driver
.get_text().strip()
1465 use_dhcp
= ( self
.dhcp_expander
.get_expanded() == False )
1467 profile
['use_dhcp'] = True
1469 profile
['use_dhcp'] = False
1470 profile
['ip'] = self
.ip
.get_text().strip()
1471 profile
['netmask'] = self
.netmask
.get_text().strip()
1472 profile
['gateway'] = self
.gw
.get_text().strip()
1473 profile
['domain'] = self
.domain
.get_text().strip()
1474 profile
['dns1'] = self
.dns1
.get_text().strip()
1475 profile
['dns2'] = self
.dns2
.get_text().strip()
1478 def set_profile( self
, profile
, known
):
1480 print "set profile: ", profile
1481 self
.essid
.set_text( profile
['essid'] )
1483 self
.essid
.set_editable( False )
1484 self
.dialog
.set_title( "WiFi Profile for %s" % profile
['essid'] )
1485 self
.bssid
.set_text( profile
['bssid'] )
1486 self
.bssid
.set_editable( False )
1487 self
.key
.set_text( profile
['key'] )
1488 self
.mode
.set_active( self
.get_array_index( profile
['mode'], WIFI_MODES
) )
1489 self
.channel
.set_active( self
.get_array_index( profile
['channel'], WIFI_CHANNELS
) )
1490 self
.security
.set_active( self
.get_array_index( profile
['security'], WIFI_SECURITY
) )
1491 #self.protocol.set_text( profile['protocol'] )
1492 self
.con_prescript
.set_text( profile
['con_prescript'] )
1493 self
.con_postscript
.set_text( profile
['con_postscript'] )
1494 self
.dis_prescript
.set_text( profile
['dis_prescript'] )
1495 self
.dis_postscript
.set_text( profile
['dis_postscript'] )
1497 if profile
['use_wpa'] == True:
1498 self
.wpa_expander
.set_expanded( True )
1499 self
.wpa_driver
.set_text( profile
['wpa_driver'] )
1501 self
.wpa_expander
.set_expanded( False )
1503 if profile
['use_dhcp'] == True:
1504 self
.dhcp_expander
.set_expanded( False)
1506 self
.dhcp_expander
.set_expanded( True )
1507 self
.ip
.set_text( profile
['ip'] )
1508 self
.netmask
.set_text( profile
['netmask'] )
1509 self
.gw
.set_text( profile
['gateway'] )
1510 self
.domain
.set_text( profile
['domain'] )
1511 self
.dns1
.set_text( profile
['dns1'] )
1512 self
.dns2
.set_text( profile
['dns2'] )
1514 def get_array_index( self
, item
, array
):
1516 return array
.index( item
.strip() )
1521 def get_array_item( self
, index
, array
):
1523 return array
[ index
]
1530 ### A simple class for putting up a "Please wait" dialog so the user
1531 ### doesn't think we've forgotten about them.
1532 class status_window
:
1533 def __init__( self
, parent
):
1534 global wifi_radar_icon
1535 self
.parent
= parent
1536 self
.dialog
= gtk
.Dialog("Working", self
.parent
.window
, gtk
.DIALOG_MODAL | gtk
.DIALOG_DESTROY_WITH_PARENT
)
1537 icon
= gtk
.gdk
.pixbuf_new_from_inline( len( wifi_radar_icon
[0] ), wifi_radar_icon
[0], False )
1538 self
.dialog
.set_icon( icon
)
1539 self
.lbl
= gtk
.Label("Please wait...")
1540 self
.bar
= gtk
.ProgressBar()
1541 self
.dialog
.vbox
.pack_start(self
.lbl
)
1542 self
.dialog
.vbox
.pack_start(self
.bar
)
1543 self
.dialog
.show_all()
1544 #self.dialog.connect("delete_event",self.inhibit_close)
1546 def update_message( self
, message
):
1547 self
.lbl
.set_text(message
)
1549 def inhibit_close( self
, widget
, signal
):
1552 def update_window( self
):
1558 self
.dialog
.show_all()
1559 self
.timer
= gobject
.timeout_add(250,self
.update_window
)
1562 def destroy( self
):
1563 gobject
.source_remove(self
.timer
)
1564 self
.dialog
.destroy()
1568 ### class to manage the configuration file
1569 class ConfigFile(ConfigParser
.SafeConfigParser
):
1570 def __init__( self
, filename
, defaults
):
1571 self
.filename
= filename
1572 self
.auto_profile_order
= []
1573 ConfigParser
.SafeConfigParser
.__init
__(self
, defaults
)
1575 def set_section( self
, section_name
, section_dict
):
1576 """ set the contents of a section to values from a dictionary """
1577 self
.add_section(section_name
)
1578 for key
in section_dict
.keys():
1579 self
.set_opt(section_name
+ "." + key
, section_dict
[key
])
1581 def get_opt( self
, option_path
):
1582 """ get a config option and handle exceptions """
1583 #print "ConfigFile.get_opt: ", option_path
1584 (section
, option
) = option_path
.split('.')
1586 return self
.get(section
, option
)
1587 except (ConfigParser
.NoSectionError
, ConfigParser
.NoOptionError
):
1590 def get_opt_as_bool( self
, option_path
):
1591 """ get a config option and return as a boolean type """
1592 option
= self
.get_opt(option_path
)
1593 if isinstance(option
, BooleanType
):
1595 if option
== 'True':
1597 if option
== 'False':
1599 raise ValueError, 'boolean option was not True or False'
1601 def get_opt_as_int( self
, option_path
):
1602 """ get a config option and return as an integer type """
1603 return int(float(self
.get_opt(option_path
)))
1605 def set_bool_opt( self
, option_path
, value
):
1606 """ convert boolean type to string and set config option """
1607 print "bool_opt: ", value
1608 if ( value
== True ) or ( value
> 0 ) or ( value
== 'True' ):
1610 elif ( value
== False ) or ( value
== 0 ) or ( value
== 'False' ):
1613 raise ValueError, 'cannot convert value to string'
1614 self
.set_opt(option_path
, repr(value
))
1616 def set_int_opt( self
, option_path
, value
):
1617 """ convert integer type to string and set config option """
1618 if not isinstance(value
, IntType
):
1619 raise ValueError, 'value is not an integer'
1620 self
.set_opt(option_path
, repr(value
))
1622 def set_float_opt( self
, option_path
, value
):
1623 """ convert float type to string and set config option """
1624 if not isinstance(value
, FloatType
):
1625 raise ValueError, 'value is not a float'
1626 self
.set_opt(option_path
, repr(int(value
)))
1628 def set_opt( self
, option_path
, value
):
1629 """ set a config option and handle exceptions """
1630 (section
, option
) = option_path
.split('.')
1632 self
.set(section
, option
, value
)
1633 except ConfigParser
.NoSectionError
:
1634 self
.add_section(section
)
1635 self
.set_opt(option_path
, value
)
1637 def profiles( self
):
1638 """ return a list of the section names which denote AP profiles """
1640 for section
in self
.sections():
1642 profile_list
.append(section
)
1646 fp
= open( self
.filename
, "r" )
1648 # convert the auto_profile_order to a list for ordering
1649 self
.auto_profile_order
= eval(self
.get_opt('DEFAULT.auto_profile_order'))
1650 print self
.auto_profile_order
1653 """ Copied from ConfigParser and modified to write options in alphabetical order """
1654 print self
.auto_profile_order
1655 self
.set_opt('DEFAULT.auto_profile_order', str(self
.auto_profile_order
))
1656 fp
= open( self
.filename
, "w" )
1657 # write DEFAULT section first
1659 fp
.write("[DEFAULT]\n")
1660 for key
in sorted(self
._defaults
.keys()):
1661 fp
.write("%s = %s\n" % (key
, str(self
._defaults
[key
]).replace('\n','\n\t')))
1663 # write non-profile sections first
1664 for section
in self
._sections
:
1665 if not section
in self
.profiles():
1666 fp
.write("[%s]\n" % section
)
1667 for key
in sorted(self
._sections
[section
].keys()):
1668 if key
!= "__name__":
1669 fp
.write("%s = %s\n" %
1670 (key
, str(self
._sections
[section
][key
]).replace('\n', '\n\t')))
1672 # write profile sections
1673 for section
in self
._sections
:
1674 if section
in self
.profiles():
1675 fp
.write("[%s]\n" % section
)
1676 for key
in sorted(self
._sections
[section
].keys()):
1677 if key
!= "__name__":
1678 fp
.write("%s = %s\n" %
1679 (key
, str(self
._sections
[section
][key
]).replace('\n', '\n\t')))
1683 ####################################################################################################
1686 if not confFile
.get_opt_as_bool('DEFAULT.speak_up'): return
1687 words
= words
.replace( "\"", "\\\"" )
1688 os
.system("%s \"%s\"" % ( confFile
.get_opt('DEFAULT.speak_command'), words
))
1689 #os.spawnlp(os.P_WAIT, confFile.get_opt('DEFAULT.speak_command'), confFile.get_opt('DEFAULT.speak_command'), words)
1692 def configure( confFile
):
1693 global main_radar_window
1696 main_radar_window
= radar_window(confFile
)
1697 lock
= threading
.RLock()
1698 threading
.Thread( None, scanning_thread
, None, ( confFile
, lock
) ).start()
1699 gobject
.timeout_add( 500, main_radar_window
.update_plist_items
)
1700 main_radar_window
.main()
1703 ####################################################################################################
1706 auto_profile_order
= []
1711 # load our conf file and known profiles
1712 ####################################################################################################
1713 # Defaults, these may get overridden by values found in the conf file.
1714 # The network interface you use.
1715 # Specify "auto_detect" as the interface to make wifi-radar automatically detect your wireless card.
1716 config_defaults
= { 'interface': "auto_detect",
1717 # How long should the scan for access points last?
1718 'scan_timeout': '5',
1719 # X1000 Linux has a say command (text to speech) to announce connecting to networks.
1720 # Set the speak_up option to false if you do not have or want this.
1721 'speak_command': '/usr/bin/say',
1722 # Should I speak up when connecting to a network? (If you have a speech command)
1723 'speak_up': 'False',
1724 # You may set this to true for cards that require a "commit" command with iwconfig
1725 'commit_required': 'False',
1726 # You may set this to true for cards that require the interface to be brought up first
1727 'ifup_required': 'False',
1728 # Set the location of several important programs
1729 'iwlist_command': '/sbin/iwlist',
1730 'iwconfig_command': '/sbin/iwconfig',
1731 'ifconfig_command': '/sbin/ifconfig',
1732 'route_command': '/sbin/route',
1733 'auto_profile_order': '[]',
1734 'version': WIFI_RADAR_VERSION
}
1736 config_dhcp
= { 'command': 'dhcpcd',
1738 'args': '-D -H -o -i dhcp_client -t %(timeout)s',
1740 'pidfile': '/var/run/dhcpcd-%(interface)s.pid' }
1742 config_wpa
= { 'command': '/usr/sbin/wpa_supplicant',
1744 'configuration': '/etc/wpa_supplicant.conf',
1746 'pidfile': '/var/run/wpa_supplicant.pid' }
1748 # initialize config, with defaults
1749 confFile
= ConfigFile(CONF_FILE
, config_defaults
)
1750 confFile
.set_section("DCHP", config_dhcp
)
1751 confFile
.set_section("WPA", config_wpa
)
1753 if not os
.path
.isfile( CONF_FILE
):
1758 ap_defaults
= { 'known': 'False',
1759 'available': 'False',
1760 'encrypted': 'False',
1766 'con_prescript': '',
1767 'con_postscript': '',
1768 'dis_prescript': '',
1769 'dis_postscript': '',
1776 # First, we add our known profiles
1777 for apname
in confFile
.profiles():
1778 ap
= ap_defaults
.copy()
1779 (ap
['essid'], ap
['bssid']) = split_section_name( apname
)
1780 # read the important values
1781 for key
in ap
.keys():
1782 ap
[key
] = confFile
.get_opt(apname
+ "." + key
)
1783 access_points
[ apname
] = ap
1784 # if it is not in the auto_profile_order add it
1785 if not apname
in confFile
.auto_profile_order
:
1786 confFile
.auto_profile_order
.append( apname
)
1788 set_network_device(confFile
.get_opt('DEFAULT.interface'))
1790 ####################################################################################################
1792 wifi_radar_icon
= [ ""
1799 "\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377"
1800 "\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\261\377\377"
1801 "\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"
1802 "\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"
1803 "\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"
1804 "\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"
1805 "\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"
1806 "\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"
1807 "\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"
1808 "\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"
1809 "\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"
1810 "\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"
1811 "\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"
1812 "\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"
1813 "\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"
1814 "\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"
1815 "\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"
1816 "\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"
1817 "\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"
1818 "\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"
1819 "\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"
1820 "\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"
1821 "\0\0\272\214\0\0\0\377\3\0\0\0\375\0\0\0\241\0\0\0\"\226\377\377\377"
1822 "\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"
1823 "\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"
1824 "\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"
1825 "\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"
1826 "\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"
1827 "\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"
1828 "\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"
1829 "\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"
1830 "\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"
1831 "\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"
1832 "\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"
1833 "\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"
1834 "\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"
1835 "\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"
1836 "\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"
1837 "\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"
1838 "\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"
1839 "\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"
1840 "\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"
1841 "\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"
1842 "\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"
1843 "\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"
1844 "\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"
1845 "\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"
1846 "\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"
1847 "\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"
1848 "\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"
1849 "\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"
1850 "\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"
1851 "\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"
1852 "\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"
1853 "\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"
1854 "\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"
1855 "\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"
1856 "\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"
1857 "\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"
1858 "\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"
1859 "\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"
1860 "\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"
1861 "\377\377\377\0\1\0\0\0a\211\0\0\0\377\1\0\0\0\257\232\377\377\377\0\1"
1862 "\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"
1863 "\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"
1864 "*\0\0\0\242\211\0\0\0\310\1\0\0\0`\205\377\377\377\0\1\0\0\0\276\211"
1865 "\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"
1866 "\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"
1867 "\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"
1868 "\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"
1869 "\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"
1870 "\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"
1871 "\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"
1872 "\377\377\377\0\1\0\0\0|\211\0\0\0\377\1\0\0\0""0\226\377\377\377\0\2"
1873 "\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"
1874 "\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"
1875 "\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"
1876 "\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"
1877 "\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"
1878 "\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"
1879 "|\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"
1880 "\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"
1881 "\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"
1882 "\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"
1883 "\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"
1884 "\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"
1885 "\377\377\0\1\0\0\0\206\207\0\0\0\310\1\0\0\0X\214\377\377\377\0\11\0"
1886 "\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"
1887 "\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"
1888 "\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"
1889 "\377\377\0\1\0\0\0\271\210\0\0\0\377\1\0\0\0\202\203\377\377\377\0\1"
1890 "\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"
1891 "\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"
1892 "\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"
1893 "\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"
1894 "\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"
1895 "\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"
1896 "\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"
1897 "\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"
1898 "\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"
1899 "\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"
1900 "\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"
1901 "\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"
1902 "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"
1903 "\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"
1904 "\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"
1905 "\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"
1906 "\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"
1907 "\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"
1908 "\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"
1909 "\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"
1910 "\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"
1911 "\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"
1912 "\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"
1913 "\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"
1914 "\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"
1915 "\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"
1916 "\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"
1917 "\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|"
1918 "\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"
1919 "\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"
1920 "\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"
1921 "\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"
1922 "\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"
1923 "\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"
1924 "\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"
1925 "\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"
1926 "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"
1927 "\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"
1928 "\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"
1929 "\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"
1930 "\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"
1931 "\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"
1932 "\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"
1933 "\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"
1934 "\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"
1935 "\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"
1936 "\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"
1937 "\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"
1938 "\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"
1939 "\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"
1940 "\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"
1941 "\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"
1942 "\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"
1943 "\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"
1944 "\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"
1945 "\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"
1946 "\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"
1947 "\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"
1948 "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"
1949 "\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"
1950 "\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"
1951 "\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"
1952 "\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"
1953 "\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"
1954 "\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"
1955 "\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"
1956 "\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"
1957 "\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"
1958 "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"
1959 "\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"
1960 "\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"
1961 "\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"
1962 "\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"
1963 "\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"
1964 "\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"
1965 "\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"
1966 "\377\377\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\377"
1967 "\377\377\377\0\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0"
1968 "\377\377\377\377\0\377\377\377\377\0\377\377\377\377\0\234\377\377\377"
1971 known_profile_icon
= [ ""
1978 "\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"
1979 "\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"
1980 "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"
1981 "\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"
1982 "\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"
1983 "\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"
1984 "\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"
1985 "\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"
1986 "\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"
1987 "\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"
1988 "\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"
1989 "\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"
1990 "\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"
1991 "\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"
1992 "\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"
1993 "\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"
1994 "\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"
1995 "\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"
1996 "\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"
1997 "***;\210\210\210\356\223\223\223\377iii\377\204\204\204\377\216\216\216"
1998 "\377~~~\377zzz\377\203\203\203\377\215\215\215\377ddd\377\202\202\202"
1999 "\377xxx\356\40\40\40;\205\0\0\0\0\2&&&#\251\251\251\353\202\374\374\374"
2000 "\377\202\372\372\372\377\5\335\335\335\377\353\353\353\377\366\366\366"
2001 "\377\327\327\327\377\357\357\357\377\202\365\365\365\377\3\362\362\362"
2002 "\377\226\226\226\353\27\27\27)\204\0\0\0\0\21,,,p\354\354\354\377\355"
2003 "\355\355\377\351\351\351\377\346\346\346\377\342\342\342\377\335\335"
2004 "\335\377\334\334\334\377\330\330\330\377\324\324\324\377\320\320\320"
2005 "\377\316\316\316\377\313\313\313\377\307\307\307\377\314\314\314\377"
2006 "\35\35\35y\0\0\0\1\202\0\0\0\0\14\0\0\0\2(((\203\357\357\357\377\345"
2007 "\345\345\377\341\341\341\377\337\337\337\377\333\333\333\377\326\326"
2008 "\326\377\322\322\322\377\316\316\316\377\312\312\312\377\306\306\306"
2009 "\377\202\302\302\302\377\30\314\314\314\377\311\311\311\377\33\33\33"
2010 "\204\0\0\0\5\0\0\0\1\0\0\0\2\0\0\0\10&&&\210\356\356\356\377\342\342"
2011 "\342\377\347\347\347\377\346\346\346\377\324GG\377\337\337\337\377\324"
2012 "GG\377\333\322\322\377\324GG\377<\341@\377\324GG\377<\341@\377\321\321"
2013 "\321\377\276\276\276\377\27\27\27\214\0\0\0\15\202\0\0\0\4+\0\0\0\21"
2014 "$$$\221\355\355\355\377\345\345\345\377\344\344\344\377\340\340\340\377"
2015 "\334\334\334\377\331\331\331\377\325\325\325\377\321\321\321\377\316"
2016 "\316\316\377\312\312\312\377\306\306\306\377\307\307\307\377\313\313"
2017 "\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"
2018 "\27\"\"\"\231\354\354\354\377\346\346\346\377\342\342\342\377\337\337"
2019 "\337\377\333\333\333\377\327\327\327\377\324\324\324\377\320\320\320"
2020 "\377\314\314\314\377\310\310\310\377\305\305\305\377\301\301\301\377"
2021 "\276\276\276\377\271\271\271\377\23\23\23\235\0\0\0\35\0\0\0\10\0\0\0"
2022 "\4\0\0\0\32\40\40\40\223\310\310\310\376\202\274\274\274\377\4\272\272"
2023 "\272\377\271\271\271\377\270\270\270\377\267\267\267\377\202\271\271"
2024 "\271\377\16\270\270\270\377\266\266\266\377\265\265\265\377\264\264\264"
2025 "\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"
2026 "\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"
2027 "\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"
2028 "\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"
2029 "\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"]
2031 unknown_profile_icon
= [ ""
2038 "\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"
2039 "\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"
2040 "\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"
2041 "\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"
2042 "(\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"
2043 "\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"
2044 "#\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"
2045 "\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"
2046 "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"
2047 "\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"
2048 "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"
2049 "\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"
2050 "\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"
2051 "\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"
2052 "\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"
2053 "\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"
2054 "\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"
2055 "\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"
2056 "\0\0\0\0\16***\21\210\210\210G\223\223\223LiiiL\204\204\204L\34=n\300"
2057 "\14""1i\361\12""0i\374\20""4j\342CXx}dddL\202\202\202LxxxG\40\40\40\21"
2058 "\205\0\0\0\0\2&&&\13\251\251\251F\202\374\374\374L\202\372\372\372L\5"
2059 "\"Cv\310Lf\217\226@]\211\245\12""0i\377\22""7n\353\202\365\365\365L\3"
2060 "\362\362\362L\226\226\226F\27\27\27\14\204\0\0\0\0\21,,,!\354\354\354"
2061 "L\355\355\355L\351\351\351L\346\346\346L\342\342\342L\335\335\335L\334"
2062 "\334\334L\210\227\255h\12""0i\377\21""6l\352\316\316\316L\313\313\313"
2063 "L\307\307\307L\314\314\314L\35\35\35$\0\0\0\1\202\0\0\0\0\14\0\0\0\1"
2064 "((('\357\357\357L\345\345\345L\341\341\341L\337\337\337L\333\333\333"
2065 "L\326\326\326L|\215\245l\20""5l\355\12""0i\374Sj\215\205\202\302\302"
2066 "\302L\4\314\314\314L\311\311\311L\33\33\33'\0\0\0\2\202\0\0\0\1\22\0"
2067 "\0\0\2&&&(\356\356\356L\342\342\342L\347\347\347L\346\346\346L\324GG"
2068 "L\337\337\337L\22""0g\351\12""0i\377^9Z\201<\341@L\324GGL<\341@L\321"
2069 "\321\321L\276\276\276L\27\27\27)\0\0\0\4\202\0\0\0\1\22\0\0\0\5$$$+\355"
2070 "\355\355L\345\345\345L\344\344\344L\340\340\340L\334\334\334L\331\331"
2071 "\331Law\227\177`u\226\177\316\316\316L\312\312\312L\306\306\306L\307"
2072 "\307\307L\313\313\313L\272\272\272L\24\24\24,\0\0\0\7\202\0\0\0\2\27"
2073 "\0\0\0\7\"\"\"-\354\354\354L\346\346\346L\342\342\342L\337\337\337L\333"
2074 "\333\333L\327\327\327LSk\217\212Qi\216\212\314\314\314L\310\310\310L"
2075 "\305\305\305L\301\301\301L\276\276\276L\271\271\271L\23\23\23/\0\0\0"
2076 "\10\0\0\0\2\0\0\0\1\0\0\0\10\40\40\40,\310\310\310K\202\274\274\274L"
2077 "\3\272\272\272L\271\271\271L\270\270\270L\202\12""0i\377\16\271\271\271"
2078 "L\270\270\270L\266\266\266L\265\265\265L\264\264\264L\231\231\231K\16"
2079 "\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"
2080 "\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"
2081 "\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"
2082 "\4\0\0\0\4\0\0\0\2\0\0\0\1\0\0\0\0"]
2084 signal_xpm_barely
= [
2111 "*%%%%=&&&&@@@@@@@@@+",
2112 "%&&&&&&&&&@@@@@@@@@+",
2113 "%&&&&&&&&&@@@@@@@@@+",
2114 "%&&&&&&&&&@@@@@@@@@+",
2115 "*%%%%%%%%%+++++++++."
2142 "$++++#@@@@@@@@@@@@@+",
2143 "+@@@@@@@@@@@@@@@@@@+",
2144 "+@@@@@@@@@@@@@@@@@@+",
2145 "+@@@@@@@@@@@@@@@@@@+",
2146 "$++++++++++++++++++."
2172 "$++++#@@@@@@@@@@@@@+",
2173 "+@@@@@@@@@@@@@@@@@@+",
2174 "+@@@@@@@@@@@@@@@@@@+",
2175 "+@@@@@@@@@@@@@@@@@@+",
2176 "$++++++++++++++++++."
2206 "=$$$$*&&&&&&&&&@@@@+",
2207 "$&&&&&&&&&&&&&&@@@@+",
2208 "$&&&&&&&&&&&&&&@@@@+",
2209 "$&&&&&&&&&&&&&&@@@@+",
2210 "=$$$$$$$$$$$$$$++++."
2239 "$%%%%#@@@@@@@@@@@@@+",
2240 "%&&&&@@@@@@@@@@@@@@+",
2241 "%&&&&@@@@@@@@@@@@@@+",
2242 "%&&&&@@@@@@@@@@@@@@+",
2243 "$%%%%++++++++++++++."
2245 signal_none_pb
= None
2246 signal_low_pb
= None
2247 signal_barely_pb
= None
2249 signal_best_pb
= None
2252 ####################################################################################################
2253 # Make so we can be imported
2254 if __name__
== "__main__":
2255 # Are we in configure mode?
2256 if len( sys
.argv
) > 1 and ( sys
.argv
[1] == '--version' or sys
.argv
[1] == '-v' ):
2257 print "WiFi-Radar version %s" % WIFI_RADAR_VERSION
2258 elif len( sys
.argv
) > 1 and ( sys
.argv
[1] == '--daemon' or sys
.argv
[1] == '-d' ):
2260 connect_to_preferred()
2263 gtk
.gdk
.threads_init()