From 080f7216b2f0b83aac194f821eac33f55eee9390 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Mon, 16 Feb 2009 10:43:57 -0500 Subject: [PATCH 01/14] curses/wicd-curses.py: Removed the redraw_tag, since I discovered that I don't need it. --- curses/wicd-curses.py | 32 +++++++++++++------------------- setup.py | 2 +- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 39b7544..4ecfe4e 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -86,32 +86,27 @@ class wrap_exceptions: try: return f(*args, **kargs) except KeyboardInterrupt: - gobject.source_remove(redraw_tag) + #gobject.source_remove(redraw_tag) loop.quit() ui.stop() print "\n"+language['terminated'] #raise except DBusException: - gobject.source_remove(redraw_tag) + #gobject.source_remove(redraw_tag) loop.quit() ui.stop() print "\n"+language['dbus_fail'] raise except : - # If the UI isn't inactive (redraw_tag wouldn't normally be - # set), then don't try to stop it, just gracefully die. - if redraw_tag != -1: - # Remove update_ui from the event queue - gobject.source_remove(redraw_tag) - # Quit the loop - loop.quit() - # Zap the screen - ui.stop() - # Print out standard notification: - print "\n" + language['exception'] - # Flush the buffer so that the notification is always above the - # backtrace - sys.stdout.flush() + # Quit the loop + loop.quit() + # Zap the screen + ui.stop() + # Print out standard notification: + print "\n" + language['exception'] + # Flush the buffer so that the notification is always above the + # backtrace + sys.stdout.flush() # Raise the exception #sleep(2) raise @@ -903,10 +898,9 @@ def main(): ui.run_wrapper(run) def run(): - global loop,redraw_tag + global loop ui.set_mouse_tracking() - redraw_tag = -1 app = appGUI() # Connect signals and whatnot to UI screen control functions @@ -919,7 +913,7 @@ def run(): 'org.wicd.daemon') loop = gobject.MainLoop() # Update what the interface looks like as an idle function - redraw_tag = gobject.idle_add(app.update_ui) + gobject.idle_add(app.update_ui) # Update the connection status on the bottom every 1.5 s. gobject.timeout_add(1500,app.update_status) gobject.idle_add(app.idle_incr) diff --git a/setup.py b/setup.py index 5c88c27..8e6308e 100755 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ import subprocess # VERSIONNUMBER VERSION_NUM = '1.6.0' REVISION_NUM = 'unknown' -CURSES_REVNO = 'r273' +CURSES_REVNO = 'r274' try: if not os.path.exists('vcsinfo.py'): From 1ab13ae61864ab91fd0270a89283bea641342ade Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Tue, 17 Feb 2009 20:04:50 -0500 Subject: [PATCH 02/14] curses/curses_misc.py: Fixed some of the arguments in MaskingEdit curses/netentry_curses.py: Added an autoconnect switch to the WirelessSettingsDialog Reformatted some code Ensured that the buttons are glued to the bottom of the dialog AUTHORS: Changed Adam's e-mail to match the ones in the man page. AUTHORS, in/man=wicd.8.in: Added/updated my e-mail in/man=wicd-curses.8.in: Removed mention of the keymap modification (too difficult/potentially problematic) Removed mention of my branch, bugs can be tagged with "wicd-curses" or something like that --- AUTHORS | 3 ++- curses/curses_misc.py | 6 ++--- curses/netentry_curses.py | 47 +++++++++++++++++++++++++-------------- in/man=wicd-curses.8.in | 11 +++------ in/man=wicd.8.in | 2 +- setup.py | 2 +- 6 files changed, 40 insertions(+), 31 deletions(-) diff --git a/AUTHORS b/AUTHORS index 745b241..0c03fec 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ -Adam Blackburn (compwiz18@users.sourceforge.net) +Adam Blackburn (compwiz18@gmail.com) Dan O'Reilly (oreilldf@gmail.com) +Andrew Psaltis (ampsaltis@gmail.com) (wicd-curses) diff --git a/curses/curses_misc.py b/curses/curses_misc.py index 9e641fc..e5079c7 100644 --- a/curses/curses_misc.py +++ b/curses/curses_misc.py @@ -110,13 +110,13 @@ class MaskingEdit(urwid.Edit): """ mask_mode = one of: "always" : everything is a '*' all of the time - "on_focus" : everything is a '*' only when not in focus + "no_focus" : everything is a '*' only when not in focus "off" : everything is always unmasked mask_char = the single character that masks all other characters in the field """ def __init__(self, caption = "", edit_text = "", multiline = False, align = 'left', wrap = 'space', allow_tab = False, - edit_pos = None, layout=None, mask_mode="masked",mask_char='*'): + edit_pos = None, layout=None, mask_mode="always",mask_char='*'): self.mask_mode = mask_mode if len(mask_char) > 1: raise MaskingEditException('Masks of more than one character are not supported!') @@ -137,7 +137,7 @@ class MaskingEdit(urwid.Edit): focus. """ # If we aren't masking anything ATM, then act like an Edit. No problems. - if self.mask_mode == "off" or (self.mask_mode == 'on_focus' and focus == True): + if self.mask_mode == "off" or (self.mask_mode == 'no_focus' and focus == True): canv = self.__super.render((maxcol,),focus) # The cache messes this thing up, because I am totally changing what # is displayed. diff --git a/curses/netentry_curses.py b/curses/netentry_curses.py index 7ff07d9..c00c887 100644 --- a/curses/netentry_curses.py +++ b/curses/netentry_curses.py @@ -54,11 +54,11 @@ class AdvancedSettingsDialog(urwid.WidgetWrap): use_static_dns_t = language['use_static_dns'] use_global_dns_t = language['use_global_dns'] - dns_dom_t = ('editcp',language['dns_domain']+': ') - search_dom_t = ('editcp',language['search_domain']+':') - dns1_t = ('editcp',language['dns']+ ' ' + language['1']+':'+' '*8) - dns2_t = ('editcp',language['dns']+ ' ' + language['2']+':'+' '*8) - dns3_t = ('editcp',language['dns']+ ' ' + language['3']+':'+' '*8) + dns_dom_t = ('editcp',language['dns_domain']+': ') + search_dom_t = ('editcp',language['search_domain']+':') + dns1_t = ('editcp',language['dns']+ ' ' + language['1']+':'+' '*8) + dns2_t = ('editcp',language['dns']+ ' ' + language['2']+':'+' '*8) + dns3_t = ('editcp',language['dns']+ ' ' + language['3']+':'+' '*8) cancel_t = 'Cancel' ok_t = 'OK' @@ -105,7 +105,7 @@ class AdvancedSettingsDialog(urwid.WidgetWrap): self._listbox = urwid.ListBox(walker) #self._frame = urwid.Frame(self._listbox) - self._frame = urwid.Frame(self._listbox) + self._frame = urwid.Frame(self._listbox,footer=self.button_cols) self.__super.__init__(self._frame) @@ -192,7 +192,12 @@ class AdvancedSettingsDialog(urwid.WidgetWrap): self.overlay.mouse_event( dim, event, button, col, row, focus=True) - self.overlay.keypress(dim, k) + k = self.overlay.keypress(dim, k) + if k in ('up','page up'): + self._w.set_focus('body') + elif k in ('down','page down'): + self._w.set_focus('footer') + if "window resize" in keys: dim = ui.get_cols_rows() if "esc" in keys or 'Q' in keys: @@ -204,6 +209,7 @@ class AdvancedSettingsDialog(urwid.WidgetWrap): if self.CANCEL_PRESSED: return False + class WiredSettingsDialog(AdvancedSettingsDialog): def __init__(self,name): global wired, daemon @@ -212,7 +218,6 @@ class WiredSettingsDialog(AdvancedSettingsDialog): #self.cur_default = # Add widgets to listbox self._w.body.body.append(self.set_default) - self._w.body.body.append(self.button_cols) self.prof_name = name title = ">"+language['configuring_wired'].replace('$A',self.prof_name) @@ -265,16 +270,19 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): self.networkID = networkID global_settings_t = language['global_settings'] encryption_t = language['use_encryption'] - + autoconnect_t = language['automatic_connect'] + self.global_settings_chkbox = urwid.CheckBox(global_settings_t) self.encryption_chkbox = urwid.CheckBox(encryption_t,on_state_change=self.encryption_toggle) self.encryption_combo = ComboBox(callback=self.combo_on_change) + self.autoconnect_chkbox = urwid.CheckBox(autoconnect_t) self.pile_encrypt = None # _w is a Frame, _w.body is a ListBox, _w.body.body is the ListWalker :-) - self._w.body.body.append(self.global_settings_chkbox) - self._w.body.body.append(self.encryption_chkbox) - self._w.body.body.append(self.encryption_combo) - self._w.body.body.append(self.button_cols) + self._listbox.body.append(urwid.Text("")) + self._listbox.body.append(self.global_settings_chkbox) + self._listbox.body.append(self.autoconnect_chkbox) + self._listbox.body.append(self.encryption_chkbox) + self._listbox.body.append(self.encryption_combo) self.encrypt_types = misc.LoadEncryptionMethods() self.set_values() @@ -306,6 +314,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): self.dns_dom_edit.set_edit_text(self.format_entry(networkID, "dns_domain")) self.search_dom_edit.set_edit_text(self.format_entry(networkID, "search_domain")) + self.autoconnect_chkbox.set_state(to_bool(self.format_entry(networkID, "automatic"))) #self.reset_static_checkboxes() self.encryption_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID, @@ -367,6 +376,10 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): #print "no encryption specified..." self.set_net_prop("enctype", "None") AdvancedSettingsDialog.save_settings(self) + + # Save the autoconnect setting. This is not where it originally was + # in the GTK UI. + self.set_net_prop("automatic",self.autoconnect_chkbox.get_state()) if self.global_settings_chkbox.get_state(): self.set_net_prop('use_settings_globally', True) @@ -385,7 +398,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): self.encryption_info = {} if self._w.body.body.__contains__(self.pile_encrypt): - self._w.body.body.pop(self._w.body.body.__len__()-2) + self._w.body.body.pop(self._w.body.body.__len__()-1) # If nothing is selected, select the first entry. if ID == -1: @@ -397,9 +410,9 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): for x in opts: edit = None if language.has_key(opts[x][0]): - edit = MaskingEdit(('editcp',language[opts[x][0].lower().replace(' ','_')]+': '),mask_mode='on_focus') + edit = MaskingEdit(('editcp',language[opts[x][0].lower().replace(' ','_')]+': '),mask_mode='no_focus') else: - edit = MaskingEdit(('editcp',opts[x][0].replace('_',' ')+': '),mask_mode='on_focus') + edit = MaskingEdit(('editcp',opts[x][0].replace('_',' ')+': '),mask_mode='no_focus') theList.append(edit) # Add the data to any array, so that the information # can be easily accessed by giving the name of the wanted @@ -410,7 +423,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): wireless.GetWirelessProperty(self.networkID, opts[x][1]))) self.pile_encrypt = DynWrap(urwid.Pile(theList),attrs=('editbx','editnfc')) - self._w.body.body.insert(self._w.body.body.__len__()-1,self.pile_encrypt) + self._w.body.body.insert(self._w.body.body.__len__(),self.pile_encrypt) #self._w.body.body.append(self.pile_encrypt) def prerun(self,ui,dim,display): diff --git a/in/man=wicd-curses.8.in b/in/man=wicd-curses.8.in index c38e426..9e0e549 100644 --- a/in/man=wicd-curses.8.in +++ b/in/man=wicd-curses.8.in @@ -64,20 +64,15 @@ Bring up instructions on how to edit the scripts. I have implemented a way to d Raise the Ad-Hoc network creation dialog .SH "FILES" -These are not used yet. .TP .I ~/.wicd/WHEREAREMYFILES Reminder that your network configuration files are not here ;-) -.TP -.I %LIB%keymap.py -Tentative location of the system keymap +.PP +These following are not used yet: .TP .I %LIB%colors.py Tentative location of the system color schemes .TP -.I ~/.wicd/keymap.py -Custom keybindings. Also where you can (later) disable the mouse. -.TP .I ~/.wicd/colors.py Custom color schemes. .SH "SEE ALSO" @@ -87,7 +82,7 @@ Custom color schemes. .SH BUGS Probably lots. ;-) -If you happen to find one, ask about it on #wicd on freenode, or submit a bug report to http://launchpad.net/wicd, branch experimental-nacl. +If you happen to find one, ask about it on #wicd on freenode, or submit a bug report to http://launchpad.net/wicd. .SH WICD-CURSES AUTHOR Andrew Psaltis diff --git a/in/man=wicd.8.in b/in/man=wicd.8.in index 55a5afb..ead0b52 100644 --- a/in/man=wicd.8.in +++ b/in/man=wicd.8.in @@ -157,7 +157,7 @@ Adam Blackburn .br Dan O'Reilly .br -Andrew Psaltis (curses client) +Andrew Psaltis (curses client) .SH MANPAGE AUTHOR Robby Workman diff --git a/setup.py b/setup.py index 8e6308e..4d27a3d 100755 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ import subprocess # VERSIONNUMBER VERSION_NUM = '1.6.0' REVISION_NUM = 'unknown' -CURSES_REVNO = 'r274' +CURSES_REVNO = 'r275' try: if not os.path.exists('vcsinfo.py'): From a62840dd960231e608836f3301f2008594a93b58 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Tue, 17 Feb 2009 23:29:14 -0500 Subject: [PATCH 03/14] Refactor wnettools/backend code so that most external tool functionality exists in wnettools, and it just inherited by the external backends. This simplifies creating new backends that just override selected methods. Rewrite encryption template parsing code to allow blank entries (though the GUI still doesn't), and be more permissive of slightly incorrect formatting. Fix bug in wicd-monitor error handling code. --- wicd/backends/be-external.py | 429 +---------------------------------- wicd/backends/be-ioctl.py | 10 +- wicd/misc.py | 49 ++-- wicd/monitor.py | 8 +- wicd/networking.py | 5 +- wicd/wicd-client.py | 2 +- wicd/wnettools.py | 407 +++++++++++++++++++++++++++++++-- 7 files changed, 427 insertions(+), 483 deletions(-) diff --git a/wicd/backends/be-external.py b/wicd/backends/be-external.py index 5d74b85..2cce772 100644 --- a/wicd/backends/be-external.py +++ b/wicd/backends/be-external.py @@ -35,9 +35,9 @@ from wicd.wnettools import * import re import os import os.path -import time - +# Regular expressions for wpa_cli output +auth_patten = re.compile('.*wpa_state=(.*?)\n', wnettools.__re_mode) NAME = "external" UPDATE_INTERVAL = 5 DESCRIPTION = """External app (original) backend @@ -49,30 +49,6 @@ it doesn't require any third party libraries and may be more stable for some set ups. """ -# Compile the regex patterns that will be used to search the output of iwlist -# scan for info these are well tested, should work on most cards -essid_pattern = re.compile('.*ESSID:"?(.*?)"?\s*\n', re.I | re.M | re.S) -ap_mac_pattern = re.compile('.*Address: (.*?)\n', re.I | re.M | re.S) -channel_pattern = re.compile('.*Channel:? ?(\d\d?)', re.I | re.M | re.S) -strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', re.I | re.M | re.S) -# These next two look a lot a like, altstrength is for Signal level = xx/100, -# which is just an alternate way of displaying link quality, signaldbm is -# for displaying actual signal strength (-xx dBm). -altstrength_pattern = re.compile('.*Signal level:?=? ?(\d\d*)', re.I | re.M | re.S) -signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)', re.I | re.M | re.S) -mode_pattern = re.compile('.*Mode:(.*?)\n', re.I | re.M | re.S) -freq_pattern = re.compile('.*Frequency:(.*?)\n', re.I | re.M | re.S) -ip_pattern = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)', re.S) -bssid_pattern = re.compile('.*Access Point: (([0-9A-Z]{2}:){5}[0-9A-Z]{2})', re.I | re.M | re.S) - -wep_pattern = re.compile('.*Encryption key:(.*?)\n', re.I | re.M | re.S) -altwpa_pattern = re.compile('(wpa_ie)', re.I | re.M | re.S) -wpa1_pattern = re.compile('(WPA Version 1)', re.I | re.M | re.S) -wpa2_pattern = re.compile('(WPA2)', re.I | re.M | re.S) - -# Patterns for wpa_cli output -auth_pattern = re.compile('.*wpa_state=(.*?)\n', re.I | re.M | re.S) - RALINK_DRIVER = 'ralink legacy' @@ -94,54 +70,6 @@ class Interface(wnettools.BaseInterface): wnettools.BaseInterface.__init__(self, iface, verbose) self.Check() - def GetIP(self, ifconfig=""): - """ Get the IP address of the interface. - - Returns: - The IP address of the interface in dotted quad form. - - """ - if not ifconfig: - cmd = 'ifconfig ' + self.iface - if self.verbose: print cmd - output = misc.Run(cmd) - else: - output = ifconfig - return misc.RunRegex(ip_pattern, output) - - def IsUp(self, ifconfig=None): - """ Determines if the interface is up. - - Returns: - True if the interface is up, False otherwise. - - """ - if not self.iface: return False - flags_file = '/sys/class/net/%s/flags' % self.iface - try: - flags = open(flags_file, "r").read().strip() - except IOError: - print "Could not open %s, using ifconfig to determine status" % flags_file - return self._slow_is_up(ifconfig) - return bool(int(flags, 16) & 1) - - - def _slow_is_up(self, ifconfig=None): - """ Determine if an interface is up using ifconfig. """ - if not ifconfig: - cmd = "ifconfig " + self.iface - if self.verbose: print cmd - output = misc.Run(cmd) - else: - output = ifconfig - lines = output.split('\n') - if len(lines) < 5: - return False - for line in lines[1:4]: - if line.strip().startswith('UP'): - return True - return False - class WiredInterface(Interface, wnettools.BaseWiredInterface): """ Control a wired network interface. """ @@ -156,97 +84,6 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): wnettools.BaseWiredInterface.__init__(self, iface, verbose) Interface.__init__(self, iface, verbose) - def GetPluggedIn(self): - """ Get the current physical connection state. - - The method will first attempt to use ethtool do determine - physical connection state. Should ethtool fail to run properly, - mii-tool will be used instead. - - Returns: - True if a link is detected, False otherwise. - - """ - if not self.iface: - return False - # check for link using /sys/class/net/iface/carrier - # is usually more accurate - sys_device = '/sys/class/net/%s/' % self.iface - carrier_path = sys_device + 'carrier' - if not self.IsUp(): - MAX_TRIES = 3 - tries = 0 - self.Up() - while True: - tries += 1 - time.sleep(2) - if self.IsUp() or tries > MAX_TRIES: break - - if os.path.exists(carrier_path): - carrier = open(carrier_path, 'r') - try: - link = carrier.read().strip() - link = int(link) - if link == 1: - return True - elif link == 0: - return False - except (IOError, ValueError, TypeError): - print 'Error checking link using /sys/class/net/%s/carrier' % self.iface - - if self.ethtool_cmd and self.link_detect in [misc.ETHTOOL, misc.AUTO]: - return self._eth_get_plugged_in() - elif self.miitool_cmd and self.link_detect in [misc.MIITOOL, misc.AUTO]: - return self._mii_get_plugged_in() - else: - print ('Error: No way of checking for a wired connection. Make ' + - 'sure that either mii-tool or ethtool is installed.') - return False - - def _eth_get_plugged_in(self): - """ Use ethtool to determine the physical connection state. - - Returns: - True if a link is detected, False otherwise. - - """ - cmd = "%s %s" % (self.ethtool_cmd, self.iface) - if not self.IsUp(): - print 'Wired Interface is down, putting it up' - self.Up() - time.sleep(6) - if self.verbose: print cmd - tool_data = misc.Run(cmd, include_stderr=True) - if misc.RunRegex(re.compile('(Link detected: yes)', re.I | re.M | re.S), - tool_data): - return True - else: - return False - - def _mii_get_plugged_in(self): - """ Use mii-tool to determine the physical connection state. - - Returns: - True if a link is detected, False otherwise. - - """ - cmd = "%s %s" % (self.miitool_cmd, self.iface) - if self.verbose: print cmd - tool_data = misc.Run(cmd, include_stderr=True) - if misc.RunRegex(re.compile('(Invalid argument)', re.I | re.M | re.S), - tool_data) is not None: - print 'Wired Interface is down, putting it up' - self.Up() - time.sleep(4) - if self.verbose: print cmd - tool_data = misc.Run(cmd, include_stderr=True) - - if misc.RunRegex(re.compile('(link ok)', re.I | re.M | re.S), - tool_data) is not None: - return True - else: - return False - class WirelessInterface(Interface, wnettools.BaseWirelessInterface): """ Control a wireless network interface. """ @@ -262,265 +99,3 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): wpa_driver) Interface.__init__(self, iface, verbose) - def GetNetworks(self): - """ Get a list of available wireless networks. - - Returns: - A list containing available wireless networks. - - """ - cmd = 'iwlist ' + self.iface + ' scan' - if self.verbose: print cmd - results = misc.Run(cmd) - # Split the networks apart, using Cell as our split point - # this way we can look at only one network at a time. - # The spaces around ' Cell ' are to minimize the chance that someone - # has an essid named Cell... - networks = results.split( ' Cell ' ) - - # Get available network info from iwpriv get_site_survey - # if we're using a ralink card (needed to get encryption info) - if self.wpa_driver == RALINK_DRIVER: - ralink_info = self._GetRalinkInfo() - else: - ralink_info = None - - # An array for the access points - access_points = [] - for cell in networks: - # Only use sections where there is an ESSID. - if 'ESSID:' in cell: - # Add this network to the list of networks - entry = self._ParseAccessPoint(cell, ralink_info) - if entry is not None: - access_points.append(entry) - - return access_points - - def _ParseAccessPoint(self, cell, ralink_info): - """ Parse a single cell from the output of iwlist. - - Keyword arguments: - cell -- string containing the cell information - ralink_info -- string contating network information needed - for ralink cards. - - Returns: - A dictionary containing the cell networks properties. - - """ - ap = {} - ap['essid'] = misc.RunRegex(essid_pattern, cell) - try: - ap['essid'] = misc.to_unicode(ap['essid']) - except (UnicodeDecodeError, UnicodeEncodeError): - print 'Unicode problem with current network essid, ignoring!!' - return None - if ap['essid'] in ['', ""]: - ap['hidden'] = True - ap['essid'] = "" - else: - ap['hidden'] = False - - # Channel - For cards that don't have a channel number, - # convert the frequency. - ap['channel'] = misc.RunRegex(channel_pattern, cell) - if ap['channel'] == None: - freq = misc.RunRegex(freq_pattern, cell) - ap['channel'] = self._FreqToChannel(freq) - - # BSSID - ap['bssid'] = misc.RunRegex(ap_mac_pattern, cell) - - # Mode - ap['mode'] = misc.RunRegex(mode_pattern, cell) - - # Break off here if we're using a ralink card - if self.wpa_driver == RALINK_DRIVER: - ap = self._ParseRalinkAccessPoint(ap, ralink_info, cell) - elif misc.RunRegex(wep_pattern, cell) == 'on': - # Encryption - Default to WEP - ap['encryption'] = True - ap['encryption_method'] = 'WEP' - - if misc.RunRegex(wpa1_pattern, cell) == 'WPA Version 1': - ap['encryption_method'] = 'WPA' - - if misc.RunRegex(altwpa_pattern, cell) == 'wpa_ie': - ap['encryption_method'] = 'WPA' - - if misc.RunRegex(wpa2_pattern, cell) == 'WPA2': - ap['encryption_method'] = 'WPA2' - else: - ap['encryption'] = False - - # Link Quality - # Set strength to -1 if the quality is not found - - # more of the patch from - # https://bugs.launchpad.net/wicd/+bug/175104 - if (strength_pattern.match(cell)): - [(strength, max_strength)] = strength_pattern.findall(cell) - if max_strength: - ap["quality"] = 100 * int(strength) // int(max_strength) - else: - ap["quality"] = int(strength) - elif misc.RunRegex(altstrength_pattern,cell): - ap['quality'] = misc.RunRegex(altstrength_pattern, cell) - else: - ap['quality'] = -1 - - # Signal Strength (only used if user doesn't want link - # quality displayed or it isn't found) - if misc.RunRegex(signaldbm_pattern, cell): - ap['strength'] = misc.RunRegex(signaldbm_pattern, cell) - elif self.wpa_driver != RALINK_DRIVER: # This is already set for ralink - ap['strength'] = -1 - - return ap - - def ValidateAuthentication(self, auth_time): - """ Validate WPA authentication. - - Validate that the wpa_supplicant authentication - process was successful. - - NOTE: It's possible this could return False, - though in reality wpa_supplicant just isn't - finished yet. - - Keyword arguments: - auth_time -- The time at which authentication began. - - Returns: - True if wpa_supplicant authenticated succesfully, - False otherwise. - - """ - # Right now there's no way to do this for these drivers - if self.wpa_driver == RALINK_DRIVER or not self.wpa_cli_cmd: - return True - - MAX_TIME = 35 - MAX_DISCONNECTED_TIME = 3 - disconnected_time = 0 - while (time.time() - auth_time) < MAX_TIME: - cmd = '%s -i %s status' % (self.wpa_cli_cmd, self.iface) - output = misc.Run(cmd) - result = misc.RunRegex(auth_pattern, output) - if self.verbose: - print 'WPA_CLI RESULT IS', result - - if not result: - return False - if result == "COMPLETED": - return True - elif result == "DISCONNECTED": - disconnected_time += 1 - if disconnected_time > MAX_DISCONNECTED_TIME: - disconnected_time = 0 - # Force a rescan to get wpa_supplicant moving again. - self._ForceSupplicantScan() - MAX_TIME += 5 - else: - disconnected_time = 0 - time.sleep(1) - - print 'wpa_supplicant authentication may have failed.' - return False - - - def _ForceSupplicantScan(self): - """ Force wpa_supplicant to rescan available networks. - - This function forces wpa_supplicant to rescan. - This works around authentication validation sometimes failing for - wpa_supplicant because it remains in a DISCONNECTED state for - quite a while, after which a rescan is required, and then - attempting to authenticate. This whole process takes a long - time, so we manually speed it up if we see it happening. - - """ - print 'wpa_supplicant rescan forced...' - cmd = 'wpa_cli -i' + self.iface + ' scan' - misc.Run(cmd) - - def StopWPA(self): - """ Terminates wpa using wpa_cli""" - cmd = 'wpa_cli -i %s terminate' % self.iface - if self.verbose: print cmd - misc.Run(cmd) - - def GetBSSID(self, iwconfig=None): - """ Get the MAC address for the interface. """ - if not iwconfig: - cmd = 'iwconfig ' + self.iface - if self.verbose: print cmd - output = misc.Run(cmd) - else: - output = iwconfig - - bssid = misc.RunRegex(bssid_pattern, output) - return bssid - - def GetSignalStrength(self, iwconfig=None): - """ Get the signal strength of the current network. - - Returns: - The signal strength. - - """ - if not iwconfig: - cmd = 'iwconfig ' + self.iface - if self.verbose: print cmd - output = misc.Run(cmd) - else: - output = iwconfig - - [(strength, max_strength)] = strength_pattern.findall(output) - if max_strength and strength: - if int(max_strength) != 0: - return 100 * int(strength) // int(max_strength) - else: - # Prevent a divide by zero error. - strength = int(strength) - - if strength is None: - strength = misc.RunRegex(altstrength_pattern, output) - - return strength - - def GetDBMStrength(self, iwconfig=None): - """ Get the dBm signal strength of the current network. - - Returns: - The dBm signal strength. - - """ - if not iwconfig: - cmd = 'iwconfig ' + self.iface - if self.verbose: print cmd - output = misc.Run(cmd) - else: - output = iwconfig - dbm_strength = misc.RunRegex(signaldbm_pattern, output) - return dbm_strength - - def GetCurrentNetwork(self, iwconfig=None): - """ Get the essid of the current network. - - Returns: - The current network essid. - - """ - if not iwconfig: - cmd = 'iwconfig ' + self.iface - if self.verbose: print cmd - output = misc.Run(cmd) - else: - output = iwconfig - network = misc.RunRegex(re.compile('.*ESSID:"(.*?)"', - re.I | re.M | re.S), output) - if network: - network = misc.to_unicode(network) - return network diff --git a/wicd/backends/be-ioctl.py b/wicd/backends/be-ioctl.py index 3ba9a48..1906865 100644 --- a/wicd/backends/be-ioctl.py +++ b/wicd/backends/be-ioctl.py @@ -33,6 +33,8 @@ from wicd import misc from wicd import wnettools from wicd import wpath from wicd.wnettools import * +from wicd.wnettools import strength_pattern, altstrength_pattern, wep_pattern, \ + signaldbm_pattern import iwscan import wpactrl @@ -58,14 +60,6 @@ Dependencies: python-wpactrl (http://projects.otaku42.de/wiki/PythonWpaCtrl) python-iwscan (http://projects.otaku42.de/browser/python-iwscan/)""" -strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', - re.I | re.M | re.S) -altstrength_pattern = re.compile('.*Signal level:?=? ?(\d\d*)', - re.I | re.M | re.S) -signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)', - re.I | re.M | re.S) -wep_pattern = re.compile('.*Encryption key:(.*?)\n', re.I | re.M | re.S) - RALINK_DRIVER = 'ralink legacy' # Got these from /usr/include/linux/wireless.h diff --git a/wicd/misc.py b/wicd/misc.py index d42418c..f4b65c5 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -57,7 +57,7 @@ ROUTE = 2 GKSUDO = 1 KDESU = 2 KTSUSS = 3 -sudo_dict = { +__sudo_dict = { AUTO : "", GKSUDO : "gksudo", KDESU : "kdesu", @@ -212,19 +212,34 @@ def ParseEncryption(network): """ enctemplate = open(wpath.encryption + network["enctype"]) template = enctemplate.readlines() - # Set these to nothing so that we can hold them outside the loop - z = "ap_scan=1\n" - # Loop through the lines in the template, selecting ones to use - for y, x in enumerate(template): - x = x.strip("\n") - if y > 4: - # replace values - x = x.replace("$_SCAN","0") - for t in network: - # Don't bother if z's value is None cause it will cause errors - if Noneify(network[t]) is not None: - x = x.replace("$_" + str(t).upper(), str(network[t])) - z = z + "\n" + x + config_file = "ap_scan=1\n" + should_replace = False + for index, line in enumerate(template): + if not should_replace: + if line.strip().startswith('---'): + should_replace = True + else: + if line.strip().startswith("}"): + # This is the last line, so we just write it. + config_file = ''.join([config_file, line]) + elif "$_" in line: + cur_val = re.findall('\$_([A-Z0-9]+)', line) + if cur_val: + if cur_val[0] == 'SCAN': + #TODO should this be hardcoded? + line = line.replace("$_SCAN", "0") + config_file = ''.join([config_file, line]) + else: + rep_val = network.get(cur_val[0].lower()) + if rep_val: + line = line.replace("$_%s" % cur_val[0], rep_val) + config_file = ''.join([config_file, line]) + else: + print "Ignoring template line: '%s'" % line + else: + print "Weird parsing error occurred" + else: # Just a regular entry. + config_file = ''.join([config_file, line]) # Write the data to the files then chmod them so they can't be read # by normal users. @@ -233,7 +248,7 @@ def ParseEncryption(network): os.chown(wpath.networks + network["bssid"].replace(":", "").lower(), 0, 0) # We could do this above, but we'd like to read protect # them before we write, so that it can't be read. - f.write(z) + f.write(config_file) f.close() def LoadEncryptionMethods(): @@ -409,7 +424,7 @@ def get_sudo_cmd(msg, prog_num=0): def choose_sudo_prog(prog_num=0): """ Try to intelligently decide which graphical sudo program to use. """ if prog_num: - return find_path(sudo_dict[prog_num]) + return find_path(__sudo_dict[prog_num]) desktop_env = detect_desktop_environment() env_path = os.environ['PATH'].split(":") paths = [] @@ -667,4 +682,4 @@ def timeout_add(time, func, milli=False): else: if not milli: time = time * 1000 return gobject.timeout_add(time, func) - \ No newline at end of file + diff --git a/wicd/monitor.py b/wicd/monitor.py index 8ff56c1..c590a10 100755 --- a/wicd/monitor.py +++ b/wicd/monitor.py @@ -45,7 +45,7 @@ daemon = dbus_dict["daemon"] wired = dbus_dict["wired"] wireless = dbus_dict["wireless"] -monitor = to_time = update_callback = None +monitor = to_time = update_callback = mainloop = None def diewithdbus(func): def wrapper(self, *__args, **__kargs): @@ -54,11 +54,11 @@ def diewithdbus(func): self.__lost_dbus_count = 0 return ret except dbusmanager.DBusException, e: - print "Caught exception %e" % str(e) + print "Caught exception %s" % str(e) if not hasattr(self, "__lost_dbus_count"): self.__lost_dbus_count = 0 if self.__lost_dbus_count > 3: - sys.exit(1) + mainloop.quit() self.__lost_dbus_count += 1 return True @@ -351,7 +351,7 @@ def main(): an amount of time determined by the active backend. """ - global monitor, to_time + global monitor, to_time, mainloop monitor = ConnectionStatus() to_time = daemon.GetBackendUpdateInterval() diff --git a/wicd/networking.py b/wicd/networking.py index b324663..8ea3fe8 100644 --- a/wicd/networking.py +++ b/wicd/networking.py @@ -152,7 +152,7 @@ class Controller(object): self.disconnect_script = None self.driver = None self.iface = None - self.backend_manager = BackendManager() + self.backend_manager = BackendManager() def get_debug(self): return self._debug def set_debug(self, value): @@ -226,7 +226,7 @@ class Controller(object): self.iface.dhcp_object = None def IsUp(self): - """ Calls the IsUp method for the wired interface. + """ Calls the IsUp method for the wired interface. Returns: True if the interface is up, False otherwise. @@ -999,3 +999,4 @@ class WiredConnectThread(ConnectThread): self.connect_result = "Success" self.is_connecting = False + diff --git a/wicd/wicd-client.py b/wicd/wicd-client.py index cc04b19..36c8ba5 100755 --- a/wicd/wicd-client.py +++ b/wicd/wicd-client.py @@ -434,7 +434,7 @@ class TrayIcon(object): """ Determines which image to use for the wireless entries. """ def fix_strength(val, default): """ Assigns given strength to a default value if needed. """ - return val is not None and int(val) or default + return val and int(val) or default def get_prop(prop): return wireless.GetWirelessProperty(net_id, prop) diff --git a/wicd/wnettools.py b/wicd/wnettools.py index 1f462d4..401b120 100644 --- a/wicd/wnettools.py +++ b/wicd/wnettools.py @@ -34,21 +34,43 @@ class WirelessInterface() -- Control a wireless network interface. import os import re import random +import time from string import maketrans, translate import wpath import misc -from misc import find_path +from misc import find_path + +# Regular expressions. +__re_mode = (re.I | re.M | re.S) +essid_pattern = re.compile('.*ESSID:"?(.*?)"?\s*\n', __re_mode) +ap_mac_pattern = re.compile('.*Address: (.*?)\n', __re_mode) +channel_pattern = re.compile('.*Channel:? ?(\d\d?)', __re_mode) +strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', __re_mode) +altstrength_pattern = re.compile('.*Signal level:?=? ?(\d\d*)', __re_mode) +signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)', __re_mode) +mode_pattern = re.compile('.*Mode:(.*?)\n', __re_mode) +freq_pattern = re.compile('.*Frequency:(.*?)\n', __re_mode) +wep_pattern = re.compile('.*Encryption key:(.*?)\n', __re_mode) +altwpa_pattern = re.compile('(wpa_ie)', __re_mode) +wpa1_pattern = re.compile('(WPA Version 1)', __re_mode) +wpa2_pattern = re.compile('(WPA2)', __re_mode) + +#iwconfig-only regular expressions. +ip_pattern = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)',re.S) +bssid_pattern = re.compile('.*Access Point: (([0-9A-Z]{2}:){5}[0-9A-Z]{2})', __re_mode) + +# Regular expressions for wpa_cli output +auth_pattern = re.compile('.*wpa_state=(.*?)\n', __re_mode) RALINK_DRIVER = 'ralink legacy' - blacklist_strict = '!"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ ' blacklist_norm = ";`$!*|><&\\" blank_trans = maketrans("", "") __all__ = ["SetDNS", "GetDefaultGateway", "GetWiredInterfaces", - "GetWirelessInterfaces", "IsValidWpaSuppDriver", "NeedsExternalCalls"] + "GetWirelessInterfaces", "IsValidWpaSuppDriver"] def _sanitize_string(string): if string: @@ -135,7 +157,6 @@ def NeedsExternalCalls(): """ Returns True if the backend needs to use an external program. """ raise NotImplementedError - def IsValidWpaSuppDriver(driver): """ Returns True if given string is a valid wpa_supplicant driver. """ output = misc.Run(["wpa_supplicant", "-D%s" % driver, "-iolan19", @@ -529,16 +550,46 @@ class BaseInterface(object): The IP address of the interface in dotted quad form. """ - raise NotImplementedError + if not ifconfig: + cmd = 'ifconfig ' + self.iface + if self.verbose: print cmd + output = misc.Run(cmd) + else: + output = ifconfig + return misc.RunRegex(ip_pattern, output) - def IsUp(self): + def IsUp(self, ifconfig=None): """ Determines if the interface is up. - + Returns: True if the interface is up, False otherwise. - + """ - raise NotImplementedError + if not self.iface: return False + flags_file = '/sys/class/net/%s/flags' % self.iface + try: + flags = open(flags_file, "r").read().strip() + except IOError: + print "Could not open %s, using ifconfig to determine status" % flags_file + return self._slow_is_up(ifconfig) + return bool(int(flags, 16) & 1) + + + def _slow_is_up(self, ifconfig=None): + """ Determine if an interface is up using ifconfig. """ + if not ifconfig: + cmd = "ifconfig " + self.iface + if self.verbose: print cmd + output = misc.Run(cmd) + else: + output = ifconfig + lines = output.split('\n') + if len(lines) < 5: + return False + for line in lines[1:4]: + if line.strip().startswith('UP'): + return True + return False class BaseWiredInterface(BaseInterface): @@ -555,17 +606,95 @@ class BaseWiredInterface(BaseInterface): def GetPluggedIn(self): """ Get the current physical connection state. - + The method will first attempt to use ethtool do determine physical connection state. Should ethtool fail to run properly, mii-tool will be used instead. + + Returns: + True if a link is detected, False otherwise. + + """ + if not self.iface: + return False + # check for link using /sys/class/net/iface/carrier + # is usually more accurate + sys_device = '/sys/class/net/%s/' % self.iface + carrier_path = sys_device + 'carrier' + if not self.IsUp(): + MAX_TRIES = 3 + tries = 0 + self.Up() + while True: + tries += 1 + time.sleep(2) + if self.IsUp() or tries > MAX_TRIES: break + + if os.path.exists(carrier_path): + carrier = open(carrier_path, 'r') + try: + link = carrier.read().strip() + link = int(link) + if link == 1: + return True + elif link == 0: + return False + except (IOError, ValueError, TypeError): + print 'Error checking link using /sys/class/net/%s/carrier' % self.iface + + if self.ethtool_cmd and self.link_detect in [misc.ETHTOOL, misc.AUTO]: + return self._eth_get_plugged_in() + elif self.miitool_cmd and self.link_detect in [misc.MIITOOL, misc.AUTO]: + return self._mii_get_plugged_in() + else: + print ('Error: No way of checking for a wired connection. Make ' + + 'sure that either mii-tool or ethtool is installed.') + return False + + def _eth_get_plugged_in(self): + """ Use ethtool to determine the physical connection state. Returns: True if a link is detected, False otherwise. """ - raise NotImplementedError - + cmd = "%s %s" % (self.ethtool_cmd, self.iface) + if not self.IsUp(): + print 'Wired Interface is down, putting it up' + self.Up() + time.sleep(6) + if self.verbose: print cmd + tool_data = misc.Run(cmd, include_stderr=True) + if misc.RunRegex(re.compile('(Link detected: yes)', re.I | re.M | re.S), + tool_data): + return True + else: + return False + + def _mii_get_plugged_in(self): + """ Use mii-tool to determine the physical connection state. + + Returns: + True if a link is detected, False otherwise. + + """ + cmd = "%s %s" % (self.miitool_cmd, self.iface) + if self.verbose: print cmd + tool_data = misc.Run(cmd, include_stderr=True) + if misc.RunRegex(re.compile('(Invalid argument)', re.I | re.M | re.S), + tool_data) is not None: + print 'Wired Interface is down, putting it up' + self.Up() + time.sleep(4) + if self.verbose: print cmd + tool_data = misc.Run(cmd, include_stderr=True) + + if misc.RunRegex(re.compile('(link ok)', re.I | re.M | re.S), + tool_data) is not None: + return True + else: + return False + class BaseWirelessInterface(BaseInterface): """ Control a wireless network interface. """ @@ -596,10 +725,6 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print str(cmd) misc.Run(cmd) - def StopWPA(self): - """ Stop wireless encryption. """ - raise NotImplementedError - def GetKillSwitchStatus(self): """ Determines if the wireless killswitch is enabled. @@ -823,10 +948,6 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print cmd misc.Run(cmd) - def ValidateAuthentication(self, auth_time): - """ Validate WPA authentication. """ - raise NotImplementedError - def _AuthenticateRalinkLegacy(self, network): """ Authenticate with the specified wireless network. @@ -866,9 +987,207 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print ' '.join(cmd) misc.Run(cmd) + def GetNetworks(self): + """ Get a list of available wireless networks. + + Returns: + A list containing available wireless networks. + + """ + cmd = 'iwlist ' + self.iface + ' scan' + if self.verbose: print cmd + results = misc.Run(cmd) + # Split the networks apart, using Cell as our split point + # this way we can look at only one network at a time. + # The spaces around ' Cell ' are to minimize the chance that someone + # has an essid named Cell... + networks = results.split( ' Cell ' ) + + # Get available network info from iwpriv get_site_survey + # if we're using a ralink card (needed to get encryption info) + if self.wpa_driver == RALINK_DRIVER: + ralink_info = self._GetRalinkInfo() + else: + ralink_info = None + + # An array for the access points + access_points = [] + for cell in networks: + # Only use sections where there is an ESSID. + if 'ESSID:' in cell: + # Add this network to the list of networks + entry = self._ParseAccessPoint(cell, ralink_info) + if entry is not None: + access_points.append(entry) + + return access_points + + def _ParseAccessPoint(self, cell, ralink_info): + """ Parse a single cell from the output of iwlist. + + Keyword arguments: + cell -- string containing the cell information + ralink_info -- string contating network information needed + for ralink cards. + + Returns: + A dictionary containing the cell networks properties. + + """ + + ap = {} + ap['essid'] = misc.RunRegex(essid_pattern, cell) + try: + ap['essid'] = misc.to_unicode(ap['essid']) + except (UnicodeDecodeError, UnicodeEncodeError): + print 'Unicode problem with current network essid, ignoring!!' + return None + if ap['essid'] in ['', ""]: + ap['hidden'] = True + ap['essid'] = "" + else: + ap['hidden'] = False + + # Channel - For cards that don't have a channel number, + # convert the frequency. + ap['channel'] = misc.RunRegex(channel_pattern, cell) + if ap['channel'] == None: + freq = misc.RunRegex(freq_pattern, cell) + ap['channel'] = self._FreqToChannel(freq) + + # BSSID + ap['bssid'] = misc.RunRegex(ap_mac_pattern, cell) + + # Mode + ap['mode'] = misc.RunRegex(mode_pattern, cell) + + # Break off here if we're using a ralink card + if self.wpa_driver == RALINK_DRIVER: + ap = self._ParseRalinkAccessPoint(ap, ralink_info, cell) + elif misc.RunRegex(wep_pattern, cell) == 'on': + # Encryption - Default to WEP + ap['encryption'] = True + ap['encryption_method'] = 'WEP' + + if misc.RunRegex(wpa1_pattern, cell) == 'WPA Version 1': + ap['encryption_method'] = 'WPA' + + if misc.RunRegex(altwpa_pattern, cell) == 'wpa_ie': + ap['encryption_method'] = 'WPA' + + if misc.RunRegex(wpa2_pattern, cell) == 'WPA2': + ap['encryption_method'] = 'WPA2' + else: + ap['encryption'] = False + + # Link Quality + # Set strength to -1 if the quality is not found + + # more of the patch from + # https://bugs.launchpad.net/wicd/+bug/175104 + if (strength_pattern.match(cell)): + [(strength, max_strength)] = strength_pattern.findall(cell) + if max_strength: + ap["quality"] = 100 * int(strength) // int(max_strength) + else: + ap["quality"] = int(strength) + elif misc.RunRegex(altstrength_pattern,cell): + ap['quality'] = misc.RunRegex(altstrength_pattern, cell) + else: + ap['quality'] = -1 + + # Signal Strength (only used if user doesn't want link + # quality displayed or it isn't found) + if misc.RunRegex(signaldbm_pattern, cell): + ap['strength'] = misc.RunRegex(signaldbm_pattern, cell) + elif self.wpa_driver != RALINK_DRIVER: # This is already set for ralink + ap['strength'] = -1 + + return ap + + def ValidateAuthentication(self, auth_time): + """ Validate WPA authentication. + + Validate that the wpa_supplicant authentication + process was successful. + + NOTE: It's possible this could return False, + though in reality wpa_supplicant just isn't + finished yet. + + Keyword arguments: + auth_time -- The time at which authentication began. + + Returns: + True if wpa_supplicant authenticated succesfully, + False otherwise. + + """ + # Right now there's no way to do this for these drivers + if self.wpa_driver == RALINK_DRIVER or not self.wpa_cli_cmd: + return True + + MAX_TIME = 35 + MAX_DISCONNECTED_TIME = 3 + disconnected_time = 0 + while (time.time() - auth_time) < MAX_TIME: + cmd = '%s -i %s status' % (self.wpa_cli_cmd, self.iface) + output = misc.Run(cmd) + result = misc.RunRegex(auth_pattern, output) + if self.verbose: + print 'WPA_CLI RESULT IS', result + + if not result: + return False + if result == "COMPLETED": + return True + elif result == "DISCONNECTED": + disconnected_time += 1 + if disconnected_time > MAX_DISCONNECTED_TIME: + disconnected_time = 0 + # Force a rescan to get wpa_supplicant moving again. + self._ForceSupplicantScan() + MAX_TIME += 5 + else: + disconnected_time = 0 + time.sleep(1) + + print 'wpa_supplicant authentication may have failed.' + return False + + + def _ForceSupplicantScan(self): + """ Force wpa_supplicant to rescan available networks. + + This function forces wpa_supplicant to rescan. + This works around authentication validation sometimes failing for + wpa_supplicant because it remains in a DISCONNECTED state for + quite a while, after which a rescan is required, and then + attempting to authenticate. This whole process takes a long + time, so we manually speed it up if we see it happening. + + """ + print 'wpa_supplicant rescan forced...' + cmd = 'wpa_cli -i' + self.iface + ' scan' + misc.Run(cmd) + + def StopWPA(self): + """ Terminates wpa using wpa_cli""" + cmd = 'wpa_cli -i %s terminate' % self.iface + if self.verbose: print cmd + misc.Run(cmd) + def GetBSSID(self, iwconfig=None): """ Get the MAC address for the interface. """ - raise NotImplementedError + if not iwconfig: + cmd = 'iwconfig ' + self.iface + if self.verbose: print cmd + output = misc.Run(cmd) + else: + output = iwconfig + + bssid = misc.RunRegex(bssid_pattern, output) + return bssid def GetSignalStrength(self, iwconfig=None): """ Get the signal strength of the current network. @@ -877,7 +1196,28 @@ class BaseWirelessInterface(BaseInterface): The signal strength. """ - raise NotImplementedError + if not iwconfig: + cmd = 'iwconfig ' + self.iface + if self.verbose: print cmd + output = misc.Run(cmd) + else: + output = iwconfig + + strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', + re.I | re.M | re.S) + altstrength_pattern = re.compile('.*Signal level:?=? ?(\d\d*)', re.I | re.M | re.S) + [(strength, max_strength)] = strength_pattern.findall(output) + if max_strength and strength: + if int(max_strength) != 0: + return 100 * int(strength) // int(max_strength) + else: + # Prevent a divide by zero error. + strength = int(strength) + + if strength is None: + strength = misc.RunRegex(altstrength_pattern, output) + + return strength def GetDBMStrength(self, iwconfig=None): """ Get the dBm signal strength of the current network. @@ -886,7 +1226,16 @@ class BaseWirelessInterface(BaseInterface): The dBm signal strength. """ - raise NotImplementedError + if not iwconfig: + cmd = 'iwconfig ' + self.iface + if self.verbose: print cmd + output = misc.Run(cmd) + else: + output = iwconfig + signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)', + re.I | re.M | re.S) + dbm_strength = misc.RunRegex(signaldbm_pattern, output) + return dbm_strength def GetCurrentNetwork(self, iwconfig=None): """ Get the essid of the current network. @@ -895,4 +1244,14 @@ class BaseWirelessInterface(BaseInterface): The current network essid. """ - raise NotImplementedError + if not iwconfig: + cmd = 'iwconfig ' + self.iface + if self.verbose: print cmd + output = misc.Run(cmd) + else: + output = iwconfig + network = misc.RunRegex(re.compile('.*ESSID:"(.*?)"', + re.I | re.M | re.S), output) + if network: + network = misc.to_unicode(network) + return network From a9fe45dcdc3a49a491b217945aeeb41c56cf943f Mon Sep 17 00:00:00 2001 From: Adam Blackburn Date: Wed, 18 Feb 2009 16:13:31 +0800 Subject: [PATCH 04/14] Updated copyright, setup.py version number, and AUTHORS --- AUTHORS | 2 +- setup.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 745b241..df3f6b5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ -Adam Blackburn (compwiz18@users.sourceforge.net) +Adam Blackburn (compwiz18@gmail.com) Dan O'Reilly (oreilldf@gmail.com) diff --git a/setup.py b/setup.py index 5c88c27..ea84e93 100755 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -# Copyright (C) 2007 - 2008 Adam Blackburn -# Copyright (C) 2007 - 2008 Dan O'Reilly +# Copyright (C) 2007 - 2009 Adam Blackburn +# Copyright (C) 2007 - 2009 Dan O'Reilly # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License Version 2 as @@ -25,7 +25,8 @@ import subprocess # Be sure to keep this updated! # VERSIONNUMBER -VERSION_NUM = '1.6.0' +VERSION_NUM = '1.6.0a1' +# REVISION_NUM is automatically updated REVISION_NUM = 'unknown' CURSES_REVNO = 'r273' From 4fc52511ba1c2984db0525750a19a44572827e73 Mon Sep 17 00:00:00 2001 From: Adam Blackburn Date: Thu, 19 Feb 2009 22:22:12 -0600 Subject: [PATCH 05/14] Fixed the dhcp_object error. --- wicd/wnettools.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wicd/wnettools.py b/wicd/wnettools.py index 401b120..2bfe775 100644 --- a/wicd/wnettools.py +++ b/wicd/wnettools.py @@ -182,6 +182,7 @@ class BaseInterface(object): self.DHCP_CLIENT = None self.flush_tool = None self.link_detect = None + self.dhcp_object = None def SetDebugMode(self, value): """ If True, verbose output is enabled. """ From 8ffe7220530bac0fdbc909bf8a6dc8599660d781 Mon Sep 17 00:00:00 2001 From: Adam Blackburn Date: Thu, 19 Feb 2009 22:59:40 -0600 Subject: [PATCH 06/14] Added check for loop before exiting loop --- curses/wicd-curses.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 4ecfe4e..488107a 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -99,7 +99,8 @@ class wrap_exceptions: raise except : # Quit the loop - loop.quit() + if 'loop' in locals(): + loop.quit() # Zap the screen ui.stop() # Print out standard notification: From d385e61b6f89823b37812d1a9a1235fb0be64cfd Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Thu, 19 Feb 2009 18:14:40 -0500 Subject: [PATCH 07/14] Fixed regex problem in wicd/misc.py. --- wicd/misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wicd/misc.py b/wicd/misc.py index f4b65c5..3e076aa 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -223,7 +223,7 @@ def ParseEncryption(network): # This is the last line, so we just write it. config_file = ''.join([config_file, line]) elif "$_" in line: - cur_val = re.findall('\$_([A-Z0-9]+)', line) + cur_val = re.findall('\$_([A-Z0-9_]+)', line) if cur_val: if cur_val[0] == 'SCAN': #TODO should this be hardcoded? From 8366c74c086fd04a8be623e74e0af9736f8107c2 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Fri, 20 Feb 2009 21:44:16 -0500 Subject: [PATCH 08/14] .bzrignore: Added files generated from the build to .bzrignore wicd/misc.py: Decode all unicode fonts before a client handles them. Prevents wicd-curses from dying due to having to display non-latin characters. --- .bzrignore | 16 ++++++++++++++++ wicd/misc.py | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index 4cb9c80..8a13d6a 100644 --- a/.bzrignore +++ b/.bzrignore @@ -3,3 +3,19 @@ install.log uninstall.log .bzrignore vcsinfo.py +build/* +init/*/* +man/wicd-curses.8 +man/wicd-manager-settings.conf.5 +man/wicd-wired-settings.conf.5 +man/wicd-wireless-settings.conf.5 +man/wicd.8 +other/50-wicd-suspend.sh +other/55wicd +other/80-wicd-connect.sh +other/WHEREAREMYFILES +other/wicd.conf +scripts/wicd +scripts/wicd-client +scripts/wicd-curses +wicd/wpath.py diff --git a/wicd/misc.py b/wicd/misc.py index 3e076aa..e0a69c6 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -529,7 +529,7 @@ def get_language_list_gui(): language['stop_showing_chooser'] = _('Stop Showing Autoconnect pop-up temporarily') language['display_type_dialog'] = _('Use dBm to measure signal strength') language['scripts'] = _('Scripts') - language['invalid_address'] = _('Invalid address in $A entry.') + #language['invalid_address'] = _('Invalid address in $A entry.') language['global_settings'] = _('Use these settings for all networks sharing this essid') language['encrypt_info_missing'] = _('Required encryption information is missing.') language['enable_encryption'] = _('This network requires encryption to be enabled.') @@ -614,6 +614,14 @@ def get_language_list_gui(): language['wicd_curses'] = _("Wicd Curses Interface") language['dbus_fail'] = _("DBus failure! This is most likely caused by the wicd daemon stopping while wicd-curses is running. Please restart the daemon, and then restart wicd-curses.") + # Fix strings in wicd-curses + for i in language.keys(): + try : + language[i] = language[i].decode('utf8') + except: + print "\"%s\"" % language[i] + raise + return language From f1920f7c7af943720d82c21b32d3a0850e2efa4c Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Fri, 20 Feb 2009 21:54:30 -0500 Subject: [PATCH 09/14] .bzrignore: Added some stuff that I missed. --- .bzrignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.bzrignore b/.bzrignore index 8a13d6a..e5f1d99 100644 --- a/.bzrignore +++ b/.bzrignore @@ -3,8 +3,10 @@ install.log uninstall.log .bzrignore vcsinfo.py +build build/* init/*/* +wpath.py* man/wicd-curses.8 man/wicd-manager-settings.conf.5 man/wicd-wired-settings.conf.5 @@ -15,6 +17,7 @@ other/55wicd other/80-wicd-connect.sh other/WHEREAREMYFILES other/wicd.conf +other/postinst scripts/wicd scripts/wicd-client scripts/wicd-curses From b7141f43cb896b1ad22f1e7f25fdbefe0fe8e923 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Sat, 21 Feb 2009 00:57:40 -0500 Subject: [PATCH 10/14] Create the wpactrl interface connection in a less bizarre way. --- wicd/backends/be-ioctl.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/wicd/backends/be-ioctl.py b/wicd/backends/be-ioctl.py index 1906865..aafe454 100644 --- a/wicd/backends/be-ioctl.py +++ b/wicd/backends/be-ioctl.py @@ -335,14 +335,16 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): def _connect_to_wpa_ctrl_iface(self): """ Connect to the wpa ctrl interface. """ ctrl_iface = '/var/run/wpa_supplicant' - try: - socket = [os.path.join(ctrl_iface, s) \ - for s in os.listdir(ctrl_iface) if s == self.iface][0] - except OSError, error: - print error + socket_loc = os.path.join(ctrl_iface, self.iface) + if os.path.exists(socket_loc): + try: + return wpactrl.WPACtrl(socket) + except wpactrl.error, e: + print "Couldn't open ctrl_interface: %s" % e + return None + else: + print "Couldn't find a wpa_supplicant ctrl_interface for iface %s" % self.iface return None - - return wpactrl.WPACtrl(socket) def ValidateAuthentication(self, auth_time): """ Validate WPA authentication. From bf0f9daf3c53543536f2f321607506af0ed781b4 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Sat, 21 Feb 2009 01:17:59 -0500 Subject: [PATCH 11/14] Force utf8 encoding in wicd-curses.py. Hopefully this won't break compat on non-utf8 consoles. --- curses/wicd-curses.py | 1 + 1 file changed, 1 insertion(+) diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 488107a..0428085 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -896,6 +896,7 @@ def main(): ('bold','white','black','bold')]) # This is a wrapper around a function that calls another a function that is a # wrapper around a infinite loop. Fun. + urwid.set_encoding('utf8') ui.run_wrapper(run) def run(): From 117240c7cdec195d52027f14b3480fe09e24a96d Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Sat, 21 Feb 2009 01:23:29 -0500 Subject: [PATCH 12/14] Added the translations to .bzrignore (hopefully that is all of it). --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index e5f1d99..4521dc6 100644 --- a/.bzrignore +++ b/.bzrignore @@ -21,4 +21,5 @@ other/postinst scripts/wicd scripts/wicd-client scripts/wicd-curses +translations/* wicd/wpath.py From 5aaaa117e7a9698a3931151aa4cd0466b1f9e6cf Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Sat, 21 Feb 2009 13:11:55 -0500 Subject: [PATCH 13/14] Fix typo --- wicd/backends/be-ioctl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wicd/backends/be-ioctl.py b/wicd/backends/be-ioctl.py index aafe454..e421ced 100644 --- a/wicd/backends/be-ioctl.py +++ b/wicd/backends/be-ioctl.py @@ -338,7 +338,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): socket_loc = os.path.join(ctrl_iface, self.iface) if os.path.exists(socket_loc): try: - return wpactrl.WPACtrl(socket) + return wpactrl.WPACtrl(socket_loc) except wpactrl.error, e: print "Couldn't open ctrl_interface: %s" % e return None From af62a5d76a3500423fef7718b9e02d86f39f3697 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Tue, 24 Feb 2009 10:28:03 -0500 Subject: [PATCH 14/14] Made the Slackware init script look more like the rest of the Slackware init scripts. --- in/init=slackware=rc.wicd.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/in/init=slackware=rc.wicd.in b/in/init=slackware=rc.wicd.in index b15439c..10b3317 100755 --- a/in/init=slackware=rc.wicd.in +++ b/in/init=slackware=rc.wicd.in @@ -5,6 +5,7 @@ # This is defined in /usr/lib/python2.5/site-packages/wicd/wpath.py PIDFILE="%PIDFILE%" +DAEMON="%SBIN%wicd" # Define start and stop functions @@ -15,7 +16,7 @@ wicd_start() { echo "$PIDFILE and try again..." exit 1 else - echo "Starting wicd daemon..." + echo "Starting wicd daemon: $DAEMON" wicd 2>/dev/null 1>&2 fi }