1
0
mirror of https://github.com/gryf/wicd.git synced 2026-01-05 21:34:16 +01:00

experimental:

- Add 3rd party python libraries used by ioctl backend to tree and to setup.py
- Port several bug fixes from the trunk (removing reliance on shell for running external commands, unicode fixes, gui crash fixes, authentication validation improvements, several others)
- Fix some crashes in ioctl backend.
- Change daemon/GUI launch scripts to use the -O flag.
This commit is contained in:
imdano
2008-10-09 18:45:01 +00:00
parent 0eba051360
commit 9ee8bc1875
40 changed files with 3412 additions and 129 deletions

View File

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
""" Network interface control tools for wicd.
@@ -253,7 +254,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
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
@@ -297,7 +298,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
ap['essid'] = misc.RunRegex(essid_pattern, cell)
try:
ap['essid'] = misc.to_unicode(ap['essid'])
except (UnicodeDecodeError, UnicodeEncodeError):
except UnicodeDecodeError, UnicodeEncodeError:
print 'Unicode problem with current network essid, ignoring!!'
return None
if ap['essid'] in ['<hidden>', ""]:
@@ -385,8 +386,9 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
if self.wpa_driver == RALINK_DRIVER or not self.WPA_CLI_FOUND:
return True
MAX_TIME = 15
MAX_TIME = 35
MAX_DISCONNECTED_TIME = 3
disconnected_time = 0
while (time.time() - auth_time) < MAX_TIME:
cmd = 'wpa_cli -i ' + self.iface + ' status'
output = misc.Run(cmd)
@@ -398,11 +400,15 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
return False
if result == "COMPLETED":
return True
elif result == "DISCONNECTED" and \
(time.time() - auth_time) > MAX_DISCONNECTED_TIME:
# Force a rescan to get wpa_supplicant moving again.
self._ForceSupplicantScan()
MAX_TIME += 5
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.'

View File

@@ -287,9 +287,14 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
"""
if not self.scan_iface:
self.scan_iface = iwscan.WirelessInterface(self.iface)
try:
self.scan_iface = iwscan.WirelessInterface(self.iface)
except (iwscan.error, e):
print "GetNetworks caught an exception: %s" %s
return []
results = self.scan_iface.Scan()
return [self._parse_ap(cell) for cell in results]
return filter(None, [self._parse_ap(cell) for cell in results])
def _parse_ap(self, cell):
""" Parse a single cell from the python-iwscan list. """
@@ -305,16 +310,18 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
ap['hidden'] = True
else:
ap['hidden'] = False
ap["channel"] = True and cell["channel"] or \
self._FreqToChannel(cell["frequency"])
if cell["channel"]:
ap["channel"] = True
else:
ap["channel"] = self._FreqToChannel(cell["frequency"])
ap["bssid"] = cell["bssid"]
ap["mode"] = cell["mode"]
if cell["enc"]:
ap["encryption"] = True
if cell["ie"]:
if cell["ie"] and cell["ie"].get('type'):
if "WPA2" in cell['ie']['type'].upper():
ap['encryption_method'] = 'WPA2'
elif "WPA" in cell['ie']['type'].upper():
@@ -383,8 +390,9 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
wpa = wpactrl.WPACtrl(socket)
MAX_TIME = 15
MAX_TIME = 35
MAX_DISCONNECTED_TIME = 3
disconnected_time = 0
while (time.time() - auth_time) < MAX_TIME:
status = wpa.request("STATUS").split("\n")
if self.verbose:
@@ -398,11 +406,14 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
result = result
if result.endswith("COMPLETED"):
return True
elif result.endswith("DISCONNECTED") and \
(time.time() - auth_time) > MAX_DISCONNECTED_TIME:
# Force a rescan to get wpa_supplicant moving again.
wpa.request("SCAN")
MAX_TIME += 5
elif result.endswith("DISCONNECTED"):
disconnected_time += 1
if disconnected_time > MAX_DISCONNECTED_TIME:
# Force a rescan to get wpa_supplicant moving again.
wpa.request("SCAN")
MAX_TIME += 5
else:
disconnected_time = 0
time.sleep(1)
print 'wpa_supplicant authentication may have failed.'

View File

@@ -284,8 +284,14 @@ class appGui(object):
height = size[1]
if width > -1 and height > -1:
self.window.resize(int(width), int(height))
else:
self.dialog.resize(gtk.gdk.screen_width() / 3,
gtk.gdk.screen_height() / 2)
gobject.timeout_add(400, self.update_statusbar)
try:
gobject.timeout_add_seconds(1, self.update_statusbar)
except:
gobject.timeout_add(1000, self.update_statusbar)
def create_adhoc_network(self, widget=None):
""" Shows a dialog that creates a new adhoc network. """
@@ -813,6 +819,7 @@ class appGui(object):
if nettype == "wireless":
if not self.check_encryption_valid(networkid,
networkentry.advanced_dialog):
self.edit_advanced(None, None, nettype, networkid, networkentry)
return False
wireless.ConnectWireless(networkid)
elif nettype == "wired":
@@ -877,12 +884,11 @@ class appGui(object):
and refresh the network list.
"""
self.window.show()
self.window.present()
self.wait_for_events()
self.is_visible = True
daemon.SetGUIOpen(True)
self.wait_for_events(0.1)
self.window.grab_focus()
gobject.idle_add(self.refresh_networks)

View File

@@ -69,6 +69,7 @@ def Run(cmd, include_stderr=False, return_pipe=False):
"""
cmd = to_unicode(str(cmd))
cmd = cmd.split()
if include_stderr:
err = STDOUT
fds = True
@@ -79,7 +80,7 @@ def Run(cmd, include_stderr=False, return_pipe=False):
tmpenv = os.environ.copy()
tmpenv["LC_ALL"] = "C"
tmpenv["LANG"] = "C"
f = Popen(cmd, shell=True, stdout=PIPE, stderr=err, close_fds=fds,
f = Popen(cmd, shell=False, stdout=PIPE, stderr=err, close_fds=fds, cwd='/',
env=tmpenv)
if return_pipe:
@@ -294,6 +295,9 @@ def get_gettext():
def to_unicode(x):
""" Attempts to convert a string to utf-8. """
# If this is a unicode string, encode it and return
if type(x) == unicode:
return x.encode('utf-8')
encoding = locale.getpreferredencoding()
try:
ret = x.decode(encoding, 'replace').encode('utf-8')
@@ -316,6 +320,7 @@ def RenameProcess(new_name):
libc.prctl(15, new_name, 0, 0, 0)
return True
except:
print "rename failed"
return False
def detect_desktop_environment():

View File

@@ -149,6 +149,12 @@ class ConnectionStatus(object):
return True
# Determine what our current state is.
# Are we currently connecting?
if daemon.CheckIfConnecting():
state = misc.CONNECTING
self.update_state(state)
return True
# Check for wired.
wired_ip = wired.GetWiredIP("")
wired_found = self.check_for_wired_connection(wired_ip)
@@ -164,21 +170,16 @@ class ConnectionStatus(object):
self.update_state(misc.WIRELESS, wifi_ip=wifi_ip)
return True
# Are we currently connecting?
if daemon.CheckIfConnecting():
state = misc.CONNECTING
else: # No connection at all.
state = misc.NOT_CONNECTED
if self.last_state == misc.WIRELESS:
from_wireless = True
else:
from_wireless = False
state = misc.NOT_CONNECTED
if self.last_state == misc.WIRELESS:
from_wireless = True
else:
from_wireless = False
self.auto_reconnect(from_wireless)
self.update_state(state)
except dbus.exceptions.DBusException, e:
print 'Ignoring DBus Error: ' + str(e)
finally:
return True
return True
def update_state(self, state, wired_ip=None, wifi_ip=None):
""" Set the current connection state. """
@@ -238,7 +239,7 @@ class ConnectionStatus(object):
# Some checks to keep reconnect retries from going crazy.
if self.reconnect_tries > 2 and \
time.time() - self.last_reconnect_time < 30:
time.time() - self.last_reconnect_time < 90:
return
self.reconnecting = True

View File

@@ -534,7 +534,8 @@ class WiredNetworkEntry(NetworkEntry):
# Center the picture and pad it a bit
self.image.set_alignment(.5, 0)
self.image.set_size_request(60, -1)
self.image.set_from_icon_name("network-wired", 6)
#self.image.set_from_icon_name("network-wired", 6)
self.image.set_from_file(wpath.images + "wired.png")
self.image.show()
self.expander.show()
self.connect_button.show()
@@ -754,8 +755,9 @@ class WirelessNetworkEntry(NetworkEntry):
self.image.set_padding(0, 0)
self.image.set_alignment(.5, 0)
self.image.set_size_request(60, -1)
self.image.set_from_icon_name("network-wired", 6)
self.essid = wireless.GetWirelessProperty(networkID, "essid")
#self.image.set_from_icon_name("network-wired", 6)
self.essid = noneToBlankString(wireless.GetWirelessProperty(networkID,
"essid"))
print "ESSID : " + self.essid
# Make the combo box.
self.lbl_strength = GreyLabel()
@@ -815,8 +817,11 @@ class WirelessNetworkEntry(NetworkEntry):
def _escape(self, val):
""" Escapes special characters so they're displayed correctly. """
#try:
return val.replace("&", "&amp;").replace("<", "&lt;").\
replace(">","&gt;").replace("'", "&apos;").replace('"', "&quot;")
replace(">","&gt;").replace("'", "&apos;").replace('"', "&quot;")
#except ValueError:
# return val
def destroy_called(self, *args):
""" Clean up everything.

View File

@@ -252,7 +252,7 @@ class ConnectThread(threading.Thread):
return message
def reset_ip_addresses(self, wiface, liface):
""" Resets the IP addresse for both wired/wireless interfaces.
""" Resets the IP addresses for both wired/wireless interfaces.
Sets a false ip so that when we set the real one, the correct
routing entry is created.
@@ -753,34 +753,18 @@ class WirelessConnectThread(ConnectThread):
def generate_psk_and_authenticate(self, wiface):
""" Generates a PSK and authenticates if necessary.
Generates a PSK using wpa_passphrase, and starts the authentication
process if encryption is on.
Generates a PSK, and starts the authentication process
if encryption is on.
"""
def _sanitize(key):
""" Escapes characters wpa_supplicant doesn't handle properly. """
new_key = []
blacklist = ["$", "`", "\""]
for c in key:
if c in blacklist:
new_key.append("\\" + c)
else:
new_key.append(c)
return ''.join(new_key)
# Check to see if we need to generate a PSK (only for non-ralink
# cards).
if self.network.get('key'):
if self.debug:
print "enctype is %s" % self.network.get('enctype')
if self.network.get('key') and 'wpa' in self.network.get('enctype'):
self.SetStatus('generating_psk')
print 'Generating psk...'
wpa_pass_path = misc.find_path('wpa_passphrase')
if wpa_pass_path:
key_pattern = re.compile('network={.*?\spsk=(.*?)\n}.*',
re.I | re.M | re.S)
cmd = ''.join([wpa_pass_path, ' "', self.network['essid'],
'" "', _sanitize(self.network['key']), '"'])
self.network['psk'] = misc.RunRegex(key_pattern, misc.Run(cmd))
self.network['psk'] = self.wiface.GeneratePSK(self.network)
if not self.network.get('psk'):
self.network['psk'] = self.network['key']

View File

@@ -83,6 +83,9 @@ class PreferencesDialog(object):
height = size[1]
if width > -1 and height > -1:
self.dialog.resize(int(width), int(height))
else:
self.dialog.resize(gtk.gdk.screen_width() / 3,
gtk.gdk.screen_height() / 2)
self.wiredcheckbox = setup_label("pref_always_check",
'wired_always_on')

View File

@@ -52,14 +52,17 @@ from wicd import misc
from wicd import gui
from wicd.dbusmanager import DBusManager
ICON_AVAIL = True
# Import egg.trayicon if we're using an older gtk version
if not (gtk.gtk_version[0] >= 2 and gtk.gtk_version[1] >= 10):
class Dummy(object): pass
gtk.StatusIcon = Dummy
try:
import egg.trayicon
USE_EGG = True
except ImportError:
print 'Unable to load wicd.py: Missing egg.trayicon module.'
sys.exit(1)
print 'Unable to load tray icon: Missing egg.trayicon module.'
ICON_AVAIL = False
else:
USE_EGG = False
@@ -96,7 +99,7 @@ class NetworkMenuItem(gtk.ImageMenuItem):
self.label.show()
class TrayIcon:
class TrayIcon(object):
""" Base Tray Icon class.
Base Class for implementing a tray icon to display network status.
@@ -110,7 +113,7 @@ class TrayIcon:
self.icon_info = self.TrayConnectionInfo(self.tr, use_tray, animate)
class TrayConnectionInfo:
class TrayConnectionInfo(object):
""" Class for updating the tray icon status. """
def __init__(self, tr, use_tray=True, animate=True):
""" Initialize variables needed for the icon status methods. """
@@ -613,7 +616,7 @@ class TrayIcon:
self.init_network_menu()
self.menu.popup(None, None, None, button, timestamp)
def set_from_file(self, path = None):
def set_from_file(self, path=None):
""" Sets a new tray icon picture. """
if not self.use_tray: return
if path != self.current_icon_path:
@@ -687,7 +690,7 @@ def main(argv):
print 'Loading...'
setup_dbus()
if not use_tray:
if not use_tray or not ICON_AVAIL:
the_gui = gui.appGui()
the_gui.standalone = True
mainloop = gobject.MainLoop()

View File

@@ -108,14 +108,19 @@ class WicdDaemon(dbus.service.Object):
self.LastScan = ''
# Kind of hackish way to set correct wnettools interfaces.
#TODO remove the need for this.
self.wifi.liface = self.wired.liface
self.wired.wiface = self.wifi.wiface
# Scan since we just got started
if auto_connect:
print "autoconnecting...", str(self.GetWirelessInterface())
self.AutoConnect(True)
print "autoconnecting if needed...", str(self.GetWirelessInterface())
if not self.auto_reconnect:
self.AutoConnect(True)
else:
self.wireless_bus.Scan()
else:
print 'scan start'
self.wireless_bus.Scan()
self.SetForcedDisconnect(True)
print "--no-autoconnect detected, not autoconnecting..."
@@ -285,6 +290,8 @@ class WicdDaemon(dbus.service.Object):
self.suspended = val
if self.suspended:
self.Disconnect()
else:
self.forced_disconnect = False
@dbus.service.method('org.wicd.daemon')
def GetSuspend(self):
@@ -1505,10 +1512,10 @@ def main(argv):
bus = dbus.SystemBus()
wicd_bus = dbus.service.BusName('org.wicd.daemon', bus=bus)
daemon = WicdDaemon(wicd_bus, auto_connect=auto_connect)
gobject.threads_init()
if not no_poll:
(child_pid, x, x, x) = gobject.spawn_async([wpath.lib + "monitor.py"],
(child_pid, x, x, x) = gobject.spawn_async(["/usr/bin/python", "-O",
wpath.lib + "monitor.py"],
flags=gobject.SPAWN_CHILD_INHERITS_STDIN)
signal.signal(signal.SIGTERM, sigterm_caught)

View File

@@ -33,6 +33,7 @@ class WirelessInterface() -- Control a wireless network interface.
import os
import re
from string import maketrans, translate, punctuation
import wpath
import misc
@@ -40,25 +41,21 @@ import misc
RALINK_DRIVER = 'ralink legacy'
blacklist_strict = punctuation.replace("-", "") + " "
blacklist_norm = ";`$!*|><&\\"
blank_trans = maketrans("", "")
def _sanitize_string(string):
""" Makes sure a string is safe to use.
Escapes characters that can be used for doing bad stuff
at the terminal.
"""
blacklist = [';', '`', '$', '!', '*', '|', '>', '<']
new_string = []
if not string:
if string:
return translate(str(string), blank_trans, blacklist_norm)
else:
return string
def _sanitize_string_strict(string):
if string:
return translate(str(string), blank_trans, blacklist_strict)
else:
return string
for char in string:
if char in blacklist:
new_string.append("\\" + char)
else:
new_string.append(char)
return ''.join(new_string)
def SetDNS(dns1=None, dns2=None, dns3=None, search_dom=None):
""" Set the DNS of the system to the specified DNS servers.
@@ -73,7 +70,7 @@ def SetDNS(dns1=None, dns2=None, dns3=None, search_dom=None):
"""
resolv = open("/etc/resolv.conf", "w")
if search_dom:
resolv.write('search %s\n' % _sanitize_string(search_dom))
resolv.write('search %s\n' % search_dom)
for dns in [dns1, dns2, dns3]:
if dns:
if misc.IsValidIP(dns):
@@ -147,7 +144,7 @@ class BaseInterface(object):
verbose -- whether to print every command run
"""
self.iface = _sanitize_string(iface)
self.iface = _sanitize_string_strict(iface)
self.verbose = verbose
self.DHCP_CLIENT = None
self.DHCP_CMD = None
@@ -169,7 +166,7 @@ class BaseInterface(object):
iface -- the name of the interface.
"""
self.iface = _sanitize_string(str(iface))
self.iface = _sanitize_string_strict(str(iface))
def _find_client_path(self, client):
""" Determines the full path for the given program.
@@ -191,21 +188,6 @@ class BaseInterface(object):
if self.verbose:
print "WARNING: No path found for %s" % (client)
return None
def _client_found(self, client):
""" Searches for the existence of the given program in PATH.
Uses "which" to determine if a given program exists in PATH.
Returns:
True if the program exists, False otherwise.
"""
client = _sanitize_string(client)
output = misc.Run("which " + client)
if output and not ("no " + client) in output:
return True
return False
def CheckDHCP(self):
""" Check for a valid DHCP client.
@@ -570,7 +552,7 @@ class BaseWirelessInterface(BaseInterface):
def SetWpaDriver(self, driver):
""" Sets the wpa_driver. """
self.wpa_driver = _sanitize_string(driver)
self.wpa_driver = _sanitize_string_strict(driver)
def SetEssid(self, essid):
""" Set the essid of the wireless interface.
@@ -579,8 +561,7 @@ class BaseWirelessInterface(BaseInterface):
essid -- essid to set the interface to
"""
essid = _sanitize_string(essid)
cmd = 'iwconfig %s essid "%s"' % (self.iface, essid)
cmd = 'iwconfig %s essid %s' % (self.iface, essid)
if self.verbose: print cmd
misc.Run(cmd)
@@ -703,7 +684,7 @@ class BaseWirelessInterface(BaseInterface):
"""
if not self.iface: return False
mode = _sanitize_string(mode)
mode = _sanitize_string_strict(mode)
if mode.lower() == 'master':
mode = 'managed'
cmd = 'iwconfig %s mode %s' % (self.iface, mode)
@@ -734,7 +715,6 @@ class BaseWirelessInterface(BaseInterface):
"""
if not self.iface: return False
key = _sanitize_string(key)
cmd = 'iwconfig %s key %s' % (self.iface, key)
if self.verbose: print cmd
misc.Run(cmd)
@@ -756,6 +736,20 @@ class BaseWirelessInterface(BaseInterface):
cmd = ''.join([cmd, ' ap ', bssid])
if self.verbose: print cmd
misc.Run(cmd)
def GeneratePSK(self, network):
""" Generate a PSK using wpa_passphrase.
Keyword arguments:
network -- dictionary containing network info
"""
wpa_pass_path = misc.find_path('wpa_passphrase')
if not wpa_pass_path: return None
key_pattern = re.compile('network={.*?\spsk=(.*?)\n}.*',
re.I | re.M | re.S)
cmd = ' '.join([wpa_pass_path, network['essid'], network['key']])
return misc.RunRegex(key_pattern, misc.Run(cmd))
def Authenticate(self, network):
""" Authenticate with the specified wireless network.
@@ -768,9 +762,9 @@ class BaseWirelessInterface(BaseInterface):
if self.wpa_driver == RALINK_DRIVER:
self._AuthenticateRalinkLegacy(network)
else:
cmd = ''.join(['wpa_supplicant -B -i ', self.iface, ' -c "',
cmd = ''.join(['wpa_supplicant -B -i ', self.iface, ' -c ',
wpath.networks, network['bssid'].replace(':','').lower(),
'" -D ', self.wpa_driver])
' -D ', self.wpa_driver])
if self.verbose: print cmd
misc.Run(cmd)