Ticket #29: nm07-support.patch
File nm07-support.patch, 170.7 KB (added by erikos, 14 years ago) |
---|
-
data/Makefile.am
diff --git a/data/Makefile.am b/data/Makefile.am index cdf9dc5..8800ad8 100644
a b GTKRC_FILES = \ 22 22 xsessionsdir = $(datadir)/xsessions 23 23 xsessions_DATA = sugar.desktop 24 24 25 nmservicedir = $(sysconfdir)/dbus-1/system.d/ 26 nmservice_DATA = nm-user-settings.conf 27 25 28 mime_xml_in_files = sugar.xml.in 26 29 mime_xml_files = $(mime_xml_in_files:.xml.in=.xml) 27 30 @INTLTOOL_XML_RULE@ … … if ENABLE_UPDATE_MIMEDB 43 46 fi 44 47 endif 45 48 46 EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $( mime_xml_in_files) em.py gtkrc.em49 EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(nmservice_DATA) $(mime_xml_in_files) em.py gtkrc.em 47 50 CLEANFILES = $(GTKRC_FILES) $(mime_xml_files) -
new file data/nm-user-settings.conf
diff --git a/data/nm-user-settings.conf b/data/nm-user-settings.conf new file mode 100644 index 0000000..af7c642
- + 1 <!DOCTYPE busconfig PUBLIC 2 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" 3 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> 4 <busconfig> 5 <policy user="root"> 6 <allow own="org.freedesktop.NetworkManagerUserSettings"/> 7 8 <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> 9 <allow send_interface="org.freedesktop.NetworkManagerSettings"/> 10 11 <!-- Only root can get secrets --> 12 <allow send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/> 13 </policy> 14 <policy at_console="true"> 15 <allow own="org.freedesktop.NetworkManagerUserSettings"/> 16 17 <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> 18 <allow send_interface="org.freedesktop.NetworkManagerSettings"/> 19 20 <!-- Only root can get secrets --> 21 <deny send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/> 22 </policy> 23 <policy context="default"> 24 <deny own="org.freedesktop.NetworkManagerUserSettings"/> 25 26 <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> 27 <allow send_interface="org.freedesktop.NetworkManagerSettings"/> 28 <!-- Only root can get secrets --> 29 <deny send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/> 30 </policy> 31 32 <limit name="max_replies_per_connection">512</limit> 33 </busconfig> 34 -
src/hardware/Makefile.am
diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am index 8cd9c77..f589d42 100644
a b sugardir = $(pkgdatadir)/shell/hardware 2 2 sugar_PYTHON = \ 3 3 __init__.py \ 4 4 hardwaremanager.py \ 5 keydialog.py \6 nmclient.py \7 nminfo.py \8 5 schoolserver.py 9 10 dbusservicedir = $(sysconfdir)/dbus-1/system.d/11 dbusservice_DATA = NetworkManagerInfo.conf12 13 EXTRA_DIST = $(dbusservice_DATA) -
deleted file src/hardware/NetworkManagerInfo.conf
diff --git a/src/hardware/NetworkManagerInfo.conf b/src/hardware/NetworkManagerInfo.conf deleted file mode 100644 index 4fb8270..0000000
+ - 1 <!DOCTYPE busconfig PUBLIC2 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"3 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">4 <busconfig>5 <policy user="root">6 <allow own="org.freedesktop.NetworkManagerInfo"/>7 8 <allow send_destination="org.freedesktop.NetworkManagerInfo"/>9 <allow send_interface="org.freedesktop.NetworkManagerInfo"/>10 </policy>11 <policy at_console="true">12 <allow own="org.freedesktop.NetworkManagerInfo"/>13 14 <allow send_destination="org.freedesktop.NetworkManagerInfo"/>15 <allow send_interface="org.freedesktop.NetworkManagerInfo"/>16 </policy>17 <policy context="default">18 <deny own="org.freedesktop.NetworkManagerInfo"/>19 20 <deny send_destination="org.freedesktop.NetworkManagerInfo"/>21 <deny send_interface="org.freedesktop.NetworkManagerInfo"/>22 </policy>23 24 <limit name="max_replies_per_connection">512</limit>25 </busconfig>26 -
src/hardware/hardwaremanager.py
diff --git a/src/hardware/hardwaremanager.py b/src/hardware/hardwaremanager.py index c4f9f75..2e5a16b 100644
a b import logging 19 19 import dbus 20 20 import gobject 21 21 22 from hardware.nmclient import NMClient23 22 from sugar.profile import get_profile 24 23 from sugar import env 25 24 from sugar import _sugarext … … class HardwareManager(gobject.GObject): 111 110 def get_manager(): 112 111 return _manager 113 112 114 def get_network_manager():115 return _network_manager116 117 113 _manager = HardwareManager() 118 114 119 try:120 _network_manager = NMClient()121 except dbus.DBusException, e:122 _network_manager = None123 logging.info('Network manager service not found.') -
deleted file src/hardware/keydialog.py
diff --git a/src/hardware/keydialog.py b/src/hardware/keydialog.py deleted file mode 100644 index 88a551f..0000000
+ - 1 # vi: ts=4 ai noet2 #3 # Copyright (C) 2006-2007 Red Hat, Inc.4 #5 # This program is free software; you can redistribute it and/or modify6 # it under the terms of the GNU General Public License as published by7 # the Free Software Foundation; either version 2 of the License, or8 # (at your option) any later version.9 #10 # This program is distributed in the hope that it will be useful,11 # but WITHOUT ANY WARRANTY; without even the implied warranty of12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13 # GNU General Public License for more details.14 #15 # You should have received a copy of the GNU General Public License16 # along with this program; if not, write to the Free Software17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA18 19 import md520 from gettext import gettext as _21 22 import gtk23 24 IW_AUTH_ALG_OPEN_SYSTEM = 0x0000000125 IW_AUTH_ALG_SHARED_KEY = 0x0000000226 27 IW_AUTH_WPA_VERSION_DISABLED = 0x0000000128 IW_AUTH_WPA_VERSION_WPA = 0x0000000229 IW_AUTH_WPA_VERSION_WPA2 = 0x0000000430 31 NM_802_11_CAP_NONE = 0x0000000032 NM_802_11_CAP_PROTO_NONE = 0x0000000133 NM_802_11_CAP_PROTO_WEP = 0x0000000234 NM_802_11_CAP_PROTO_WPA = 0x0000000435 NM_802_11_CAP_PROTO_WPA2 = 0x0000000836 NM_802_11_CAP_KEY_MGMT_PSK = 0x0000004037 NM_802_11_CAP_KEY_MGMT_802_1X = 0x0000008038 NM_802_11_CAP_CIPHER_WEP40 = 0x0000100039 NM_802_11_CAP_CIPHER_WEP104 = 0x0000200040 NM_802_11_CAP_CIPHER_TKIP = 0x0000400041 NM_802_11_CAP_CIPHER_CCMP = 0x0000800042 43 NM_AUTH_TYPE_WPA_PSK_AUTO = 0x0000000044 IW_AUTH_CIPHER_NONE = 0x0000000145 IW_AUTH_CIPHER_WEP40 = 0x0000000246 IW_AUTH_CIPHER_TKIP = 0x0000000447 IW_AUTH_CIPHER_CCMP = 0x0000000848 IW_AUTH_CIPHER_WEP104 = 0x0000001049 50 IW_AUTH_KEY_MGMT_802_1X = 0x151 IW_AUTH_KEY_MGMT_PSK = 0x252 53 def string_is_hex(key):54 is_hex = True55 for c in key:56 if not 'a' <= c.lower() <= 'f' and not '0' <= c <= '9':57 is_hex = False58 return is_hex59 60 def string_is_ascii(string):61 try:62 string.encode('ascii')63 return True64 except UnicodeEncodeError:65 return False66 67 def string_to_hex(passphrase):68 key = ''69 for c in passphrase:70 key += '%02x' % ord(c)71 return key72 73 def hash_passphrase(passphrase):74 # passphrase must have a length of 6475 if len(passphrase) > 64:76 passphrase = passphrase[:64]77 elif len(passphrase) < 64:78 while len(passphrase) < 64:79 passphrase += passphrase[:64 - len(passphrase)]80 passphrase = md5.new(passphrase).digest()81 return string_to_hex(passphrase)[:26]82 83 class KeyDialog(gtk.Dialog):84 def __init__(self, net, async_cb, async_err_cb):85 gtk.Dialog.__init__(self, flags=gtk.DIALOG_MODAL)86 self.set_title("Wireless Key Required")87 88 self._net = net89 self._async_cb = async_cb90 self._async_err_cb = async_err_cb91 self._entry = None92 93 self.set_has_separator(False)94 95 label = gtk.Label("A wireless encryption key is required for\n" \96 " the wireless network '%s'." % net.get_ssid())97 self.vbox.pack_start(label)98 99 self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,100 gtk.STOCK_OK, gtk.RESPONSE_OK)101 self.set_default_response(gtk.RESPONSE_OK)102 self.set_has_separator(True)103 104 def add_key_entry(self):105 self._entry = gtk.Entry()106 #self._entry.props.visibility = False107 self._entry.connect('changed', self._update_response_sensitivity)108 self._entry.connect('activate', self._entry_activate_cb)109 self.vbox.pack_start(self._entry)110 self.vbox.set_spacing(6)111 self.vbox.show_all()112 113 self._update_response_sensitivity()114 self._entry.grab_focus()115 116 def _entry_activate_cb(self, entry):117 self.response(gtk.RESPONSE_OK)118 119 def create_security(self):120 raise NotImplementedError121 122 def get_network(self):123 return self._net124 125 def get_callbacks(self):126 return (self._async_cb, self._async_err_cb)127 128 WEP_PASSPHRASE = 1129 WEP_HEX = 2130 WEP_ASCII = 3131 132 class WEPKeyDialog(KeyDialog):133 def __init__(self, net, async_cb, async_err_cb):134 KeyDialog.__init__(self, net, async_cb, async_err_cb)135 136 # WEP key type137 self.key_store = gtk.ListStore(str, int)138 self.key_store.append(["Passphrase (128-bit)", WEP_PASSPHRASE])139 self.key_store.append(["Hex (40/128-bit)", WEP_HEX])140 self.key_store.append(["ASCII (40/128-bit)", WEP_ASCII])141 142 self.key_combo = gtk.ComboBox(self.key_store)143 cell = gtk.CellRendererText()144 self.key_combo.pack_start(cell, True)145 self.key_combo.add_attribute(cell, 'text', 0)146 self.key_combo.set_active(0)147 self.key_combo.connect('changed', self._key_combo_changed_cb)148 149 hbox = gtk.HBox()150 hbox.pack_start(gtk.Label(_("Key Type:")))151 hbox.pack_start(self.key_combo)152 hbox.show_all()153 self.vbox.pack_start(hbox)154 155 # Key entry field156 self.add_key_entry()157 158 # WEP authentication mode159 self.auth_store = gtk.ListStore(str, int)160 self.auth_store.append(["Open System", IW_AUTH_ALG_OPEN_SYSTEM])161 self.auth_store.append(["Shared Key", IW_AUTH_ALG_SHARED_KEY])162 163 self.auth_combo = gtk.ComboBox(self.auth_store)164 cell = gtk.CellRendererText()165 self.auth_combo.pack_start(cell, True)166 self.auth_combo.add_attribute(cell, 'text', 0)167 self.auth_combo.set_active(0)168 169 hbox = gtk.HBox()170 hbox.pack_start(gtk.Label(_("Authentication Type:")))171 hbox.pack_start(self.auth_combo)172 hbox.show_all()173 174 self.vbox.pack_start(hbox)175 176 def _key_combo_changed_cb(self, widget):177 self._update_response_sensitivity()178 179 def _get_security(self):180 key = self._entry.get_text()181 182 it = self.key_combo.get_active_iter()183 (key_type, ) = self.key_store.get(it, 1)184 185 if key_type == WEP_PASSPHRASE:186 key = hash_passphrase(key)187 elif key_type == WEP_ASCII:188 key = string_to_hex(key)189 190 it = self.auth_combo.get_active_iter()191 (auth_alg, ) = self.auth_store.get(it, 1)192 193 we_cipher = None194 if len(key) == 26:195 we_cipher = IW_AUTH_CIPHER_WEP104196 elif len(key) == 10:197 we_cipher = IW_AUTH_CIPHER_WEP40198 199 return (we_cipher, key, auth_alg)200 201 def print_security(self):202 (we_cipher, key, auth_alg) = self._get_security()203 print "Cipher: %d" % we_cipher204 print "Key: %s" % key205 print "Auth: %d" % auth_alg206 207 def create_security(self):208 (we_cipher, key, auth_alg) = self._get_security()209 from nminfo import Security210 return Security.new_from_args(we_cipher, (key, auth_alg))211 212 def _update_response_sensitivity(self, ignored=None):213 key = self._entry.get_text()214 it = self.key_combo.get_active_iter()215 (key_type, ) = self.key_store.get(it, 1)216 217 valid = False218 if key_type == WEP_PASSPHRASE:219 # As the md5 passphrase can be of any length and has no indicator,220 # we cannot check for the validity of the input.221 if len(key) > 0:222 valid = True223 elif key_type == WEP_ASCII:224 if len(key) == 5 or len(key) == 13:225 valid = string_is_ascii(key)226 elif key_type == WEP_HEX:227 if len(key) == 10 or len(key) == 26:228 valid = string_is_hex(key)229 230 self.set_response_sensitive(gtk.RESPONSE_OK, valid)231 232 class WPAKeyDialog(KeyDialog):233 def __init__(self, net, async_cb, async_err_cb):234 KeyDialog.__init__(self, net, async_cb, async_err_cb)235 self.add_key_entry()236 237 self.store = gtk.ListStore(str, int)238 self.store.append(["Automatic", NM_AUTH_TYPE_WPA_PSK_AUTO])239 if net.get_caps() & NM_802_11_CAP_CIPHER_CCMP:240 self.store.append(["AES-CCMP", IW_AUTH_CIPHER_CCMP])241 if net.get_caps() & NM_802_11_CAP_CIPHER_TKIP:242 self.store.append(["TKIP", IW_AUTH_CIPHER_TKIP])243 244 self.combo = gtk.ComboBox(self.store)245 cell = gtk.CellRendererText()246 self.combo.pack_start(cell, True)247 self.combo.add_attribute(cell, 'text', 0)248 self.combo.set_active(0)249 250 self.hbox = gtk.HBox()251 self.hbox.pack_start(gtk.Label(_("Encryption Type:")))252 self.hbox.pack_start(self.combo)253 self.hbox.show_all()254 255 self.vbox.pack_start(self.hbox)256 257 def _get_security(self):258 ssid = self.get_network().get_ssid()259 key = self._entry.get_text()260 is_hex = string_is_hex(key)261 262 real_key = None263 if len(key) == 64 and is_hex:264 # Hex key265 real_key = key266 elif len(key) >= 8 and len(key) <= 63:267 # passphrase268 from subprocess import Popen, PIPE269 p = Popen(['/usr/sbin/wpa_passphrase', ssid, key], stdout=PIPE)270 for line in p.stdout:271 if line.strip().startswith("psk="):272 real_key = line.strip()[4:]273 if p.wait() != 0:274 raise RuntimeError("Error hashing passphrase")275 if real_key and len(real_key) != 64:276 real_key = None277 278 if not real_key:279 raise RuntimeError("Invalid key")280 281 it = self.combo.get_active_iter()282 (we_cipher, ) = self.store.get(it, 1)283 284 wpa_ver = IW_AUTH_WPA_VERSION_WPA285 caps = self.get_network().get_caps()286 if caps & NM_802_11_CAP_PROTO_WPA2:287 wpa_ver = IW_AUTH_WPA_VERSION_WPA2288 289 return (we_cipher, real_key, wpa_ver)290 291 def print_security(self):292 (we_cipher, key, wpa_ver) = self._get_security()293 print "Cipher: %d" % we_cipher294 print "Key: %s" % key295 print "WPA Ver: %d" % wpa_ver296 297 def create_security(self):298 (we_cipher, key, wpa_ver) = self._get_security()299 from nminfo import Security300 return Security.new_from_args(we_cipher,301 (key, wpa_ver, IW_AUTH_KEY_MGMT_PSK))302 303 def _update_response_sensitivity(self, ignored=None):304 key = self._entry.get_text()305 is_hex = string_is_hex(key)306 307 valid = False308 if len(key) == 64 and is_hex:309 # hex key310 valid = True311 elif len(key) >= 8 and len(key) <= 63:312 # passphrase313 valid = True314 self.set_response_sensitive(gtk.RESPONSE_OK, valid)315 return False316 317 def new_key_dialog(net, async_cb, async_err_cb):318 caps = net.get_caps()319 if (caps & NM_802_11_CAP_CIPHER_TKIP or caps & NM_802_11_CAP_CIPHER_CCMP) \320 and (caps & NM_802_11_CAP_PROTO_WPA or \321 caps & NM_802_11_CAP_PROTO_WPA2):322 return WPAKeyDialog(net, async_cb, async_err_cb)323 elif (caps & NM_802_11_CAP_CIPHER_WEP40 or \324 caps & NM_802_11_CAP_CIPHER_WEP104) and \325 (caps & NM_802_11_CAP_PROTO_WEP):326 return WEPKeyDialog(net, async_cb, async_err_cb)327 else:328 raise RuntimeError("Unhandled network capabilities %x" % caps)329 330 331 332 class FakeNet(object):333 def get_ssid(self):334 return "olpcwpa"335 336 def get_caps(self):337 return NM_802_11_CAP_CIPHER_CCMP | NM_802_11_CAP_CIPHER_TKIP | \338 NM_802_11_CAP_PROTO_WPA339 340 def response_cb(widget, response_id):341 if response_id == gtk.RESPONSE_OK:342 print dialog.print_security()343 else:344 print "canceled"345 widget.hide()346 widget.destroy()347 348 349 if __name__ == "__main__":350 fake_net = FakeNet()351 dialog = new_key_dialog(fake_net, None, None)352 dialog.connect("response", response_cb)353 dialog.run()354 -
deleted file src/hardware/nmclient.py
diff --git a/src/hardware/nmclient.py b/src/hardware/nmclient.py deleted file mode 100644 index c517391..0000000
+ - 1 #2 # Copyright (C) 2006-2007 Red Hat, Inc.3 #4 # This program is free software; you can redistribute it and/or modify5 # it under the terms of the GNU General Public License as published by6 # the Free Software Foundation; either version 2 of the License, or7 # (at your option) any later version.8 #9 # This program is distributed in the hope that it will be useful,10 # but WITHOUT ANY WARRANTY; without even the implied warranty of11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12 # GNU General Public License for more details.13 #14 # You should have received a copy of the GNU General Public License15 # along with this program; if not, write to the Free Software16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA17 18 import logging19 20 import dbus21 import dbus.glib22 import dbus.decorators23 import gobject24 25 from hardware import nminfo26 from sugar.graphics import xocolor27 28 IW_AUTH_ALG_OPEN_SYSTEM = 0x0000000129 IW_AUTH_ALG_SHARED_KEY = 0x0000000230 31 NM_DEVICE_STAGE_STRINGS = ("Unknown",32 "Prepare",33 "Config",34 "Need Users Key",35 "IP Config",36 "IP Config Get",37 "IP Config Commit",38 "Activated",39 "Failed",40 "Canceled"41 )42 43 NM_SERVICE = 'org.freedesktop.NetworkManager'44 NM_IFACE = 'org.freedesktop.NetworkManager'45 NM_IFACE_DEVICES = 'org.freedesktop.NetworkManager.Devices'46 NM_PATH = '/org/freedesktop/NetworkManager'47 48 DEVICE_TYPE_UNKNOWN = 049 DEVICE_TYPE_802_3_ETHERNET = 150 DEVICE_TYPE_802_11_WIRELESS = 251 DEVICE_TYPE_802_11_MESH_OLPC = 352 53 NM_DEVICE_CAP_NONE = 0x0000000054 NM_DEVICE_CAP_NM_SUPPORTED = 0x0000000155 NM_DEVICE_CAP_CARRIER_DETECT = 0x0000000256 NM_DEVICE_CAP_WIRELESS_SCAN = 0x0000000457 58 sys_bus = dbus.SystemBus()59 60 NM_802_11_CAP_NONE = 0x0000000061 NM_802_11_CAP_PROTO_NONE = 0x0000000162 NM_802_11_CAP_PROTO_WEP = 0x0000000263 NM_802_11_CAP_PROTO_WPA = 0x0000000464 NM_802_11_CAP_PROTO_WPA2 = 0x0000000865 NM_802_11_CAP_KEY_MGMT_PSK = 0x0000004066 NM_802_11_CAP_KEY_MGMT_802_1X = 0x0000008067 NM_802_11_CAP_CIPHER_WEP40 = 0x0000100068 NM_802_11_CAP_CIPHER_WEP104 = 0x0000200069 NM_802_11_CAP_CIPHER_TKIP = 0x0000400070 NM_802_11_CAP_CIPHER_CCMP = 0x0000800071 72 NETWORK_STATE_CONNECTING = 073 NETWORK_STATE_CONNECTED = 174 NETWORK_STATE_NOTCONNECTED = 275 76 DEVICE_STATE_ACTIVATING = 077 DEVICE_STATE_ACTIVATED = 178 DEVICE_STATE_INACTIVE = 279 80 IW_MODE_ADHOC = 181 IW_MODE_INFRA = 282 83 class Network(gobject.GObject):84 __gsignals__ = {85 'initialized' : (gobject.SIGNAL_RUN_FIRST,86 gobject.TYPE_NONE, ([gobject.TYPE_BOOLEAN])),87 'strength-changed': (gobject.SIGNAL_RUN_FIRST,88 gobject.TYPE_NONE, ([])),89 'state-changed' : (gobject.SIGNAL_RUN_FIRST,90 gobject.TYPE_NONE, ([]))91 }92 93 def __init__(self, client, op):94 gobject.GObject.__init__(self)95 self._client = client96 self._op = op97 self._ssid = None98 self._mode = None99 self._strength = 0100 self._caps = 0101 self._valid = False102 self._favorite = False103 self._state = NETWORK_STATE_NOTCONNECTED104 105 obj = sys_bus.get_object(NM_SERVICE, self._op)106 net = dbus.Interface(obj, NM_IFACE_DEVICES)107 net.getProperties(reply_handler=self._update_reply_cb,108 error_handler=self._update_error_cb)109 110 def _update_reply_cb(self, *props):111 self._ssid = props[1]112 self._strength = props[3]113 self._mode = props[6]114 self._caps = props[7]115 if self._caps & NM_802_11_CAP_PROTO_WPA or \116 self._caps & NM_802_11_CAP_PROTO_WPA2:117 if not (self._caps & NM_802_11_CAP_KEY_MGMT_PSK):118 # 802.1x is not supported at this time119 logging.debug("Net(%s): ssid '%s' dropping because 802.1x" \120 "is unsupported" % (self._op, self._ssid))121 self._valid = False122 self.emit('initialized', self._valid)123 return124 if self._mode != IW_MODE_INFRA:125 # Don't show Ad-Hoc networks; they usually don't DHCP and therefore126 # won't work well here. This also works around the bug where127 # we show our own mesh SSID on the Mesh view when in mesh mode128 logging.debug("Net(%s): ssid '%s' is adhoc; not showing" %129 (self._op, self._ssid))130 self._valid = False131 self.emit('initialized', self._valid)132 return133 134 fav_nets = []135 if self._client.nminfo:136 fav_nets = self._client.nminfo.get_networks(137 nminfo.NETWORK_TYPE_ALLOWED)138 if self._ssid in fav_nets:139 self._favorite = True140 141 self._valid = True142 logging.debug("Net(%s): caps 0x%X" % (self._ssid, self._caps))143 self.emit('initialized', self._valid)144 145 def _update_error_cb(self, err):146 logging.debug("Net(%s): failed to update. (%s)" % (self._op, err))147 self._valid = False148 self.emit('initialized', self._valid)149 150 def get_colors(self):151 import sha152 sh = sha.new()153 data = self._ssid + hex(self._caps) + hex(self._mode)154 sh.update(data)155 h = hash(sh.digest())156 idx = h % len(xocolor.colors)157 # stroke, fill158 return (xocolor.colors[idx][0], xocolor.colors[idx][1])159 160 def get_ssid(self):161 return self._ssid162 163 def get_caps(self):164 return self._caps165 166 def get_mode(self):167 return self._mode168 169 def get_state(self):170 return self._state171 172 def set_state(self, state):173 if state == self._state:174 return175 self._state = state176 if self._valid:177 self.emit('state-changed')178 179 def get_op(self):180 return self._op181 182 def get_strength(self):183 return self._strength184 185 def set_strength(self, strength):186 if strength == self._strength:187 return188 self._strength = strength189 if self._valid:190 self.emit('strength-changed')191 192 def is_valid(self):193 return self._valid194 195 def is_favorite(self):196 return self._favorite197 198 class Device(gobject.GObject):199 __gsignals__ = {200 'initialized': (gobject.SIGNAL_RUN_FIRST,201 gobject.TYPE_NONE, ([])),202 'init-failed': (gobject.SIGNAL_RUN_FIRST,203 gobject.TYPE_NONE, ([])),204 'ssid-changed': (gobject.SIGNAL_RUN_FIRST,205 gobject.TYPE_NONE, ([])),206 'strength-changed': (gobject.SIGNAL_RUN_FIRST,207 gobject.TYPE_NONE, ([])),208 'state-changed': (gobject.SIGNAL_RUN_FIRST,209 gobject.TYPE_NONE, ([])),210 'activation-stage-changed': (gobject.SIGNAL_RUN_FIRST,211 gobject.TYPE_NONE, ([])),212 'network-appeared': (gobject.SIGNAL_RUN_FIRST,213 gobject.TYPE_NONE,214 ([gobject.TYPE_PYOBJECT])),215 'network-disappeared': (gobject.SIGNAL_RUN_FIRST,216 gobject.TYPE_NONE,217 ([gobject.TYPE_PYOBJECT])),218 'ip-changed': (gobject.SIGNAL_RUN_FIRST,219 gobject.TYPE_NONE, ([])),220 }221 222 def __init__(self, client, op):223 gobject.GObject.__init__(self)224 self._client = client225 self._op = op226 self._iface = None227 self._type = DEVICE_TYPE_UNKNOWN228 self._udi = None229 self._active = False230 self._act_stage = 0231 self._strength = 0232 self._freq = 0.0233 self._link = False234 self._valid = False235 self._networks = {}236 self._caps = 0237 self._state = DEVICE_STATE_INACTIVE238 self._active_network = None239 self._active_net_sigid = 0240 self._ip_address = None241 242 obj = sys_bus.get_object(NM_SERVICE, self._op)243 self.dev = dbus.Interface(obj, NM_IFACE_DEVICES)244 self.dev.getProperties(reply_handler=self._update_reply_cb,245 error_handler=self._update_error_cb)246 247 def _is_activating(self):248 if self._active and self._act_stage >= 1 and self._act_stage <= 6:249 return True250 return False251 252 def _is_activated(self):253 if self._active and self._act_stage == 7:254 return True255 return False256 257 # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2258 def _getproperties_for_ip_only_reply_cb(self, *props):259 current_ip = props[6]260 if current_ip != self._ip_address:261 self._ip_address = current_ip262 if self._valid:263 self.emit('ip-changed')264 265 # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2266 def _getproperties_for_ip_only_error_cb(self, err):267 logging.warning("Device(%s): failed to update. (%s)" % (self._op, err))268 269 def _update_reply_cb(self, *props):270 self._iface = props[1]271 self._type = props[2]272 self._udi = props[3]273 self._active = props[4]274 self._act_stage = props[5]275 self._link = props[15]276 self._caps = props[17]277 278 if self._type == DEVICE_TYPE_802_11_WIRELESS:279 old_strength = self._strength280 self._strength = props[14]281 if self._strength != old_strength:282 if self._valid:283 self.emit('strength-changed')284 self._update_networks(props[20], props[19])285 elif self._type == DEVICE_TYPE_802_11_MESH_OLPC:286 old_strength = self._strength287 self._strength = props[14]288 if self._strength != old_strength:289 if self._valid:290 self.emit('strength-changed')291 292 self._valid = True293 294 # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2295 if props[6] != self._ip_address:296 self._ip_address = props[6]297 self.emit('ip-changed')298 299 if self._is_activating():300 self.set_state(DEVICE_STATE_ACTIVATING)301 elif self._is_activated():302 self.set_state(DEVICE_STATE_ACTIVATED)303 else:304 self.set_state(DEVICE_STATE_INACTIVE)305 306 self.emit('initialized')307 308 def _update_networks(self, net_ops, active_op):309 for op in net_ops:310 net = Network(self._client, op)311 self._networks[op] = net312 net.connect('initialized', lambda *args:313 self._net_initialized_cb(active_op, *args))314 315 def _update_error_cb(self, err):316 logging.debug("Device(%s): failed to update. (%s)" % (self._op, err))317 self._valid = False318 self.emit('init-failed')319 320 def _net_initialized_cb(self, active_op, net, valid):321 net_op = net.get_op()322 if not self._networks.has_key(net_op):323 return324 325 if not valid:326 # init failure327 del self._networks[net_op]328 return329 330 # init success331 if self._valid:332 self.emit('network-appeared', net)333 if active_op and net_op == active_op:334 self.set_active_network(net)335 336 def get_op(self):337 return self._op338 339 def get_networks(self):340 ret = []341 for net in self._networks.values():342 if net.is_valid():343 ret.append(net)344 return ret345 346 def get_network(self, op):347 if self._networks.has_key(op) and self._networks[op].is_valid():348 return self._networks[op]349 return None350 351 def get_network_ops(self):352 ret = []353 for net in self._networks.values():354 if net.is_valid():355 ret.append(net.get_op())356 return ret357 358 def get_mesh_step(self):359 if self._type != DEVICE_TYPE_802_11_MESH_OLPC:360 raise RuntimeError("Only valid for mesh devices")361 try:362 step = self.dev.getMeshStep(timeout=3)363 except dbus.DBusException:364 step = 0365 return step366 367 def get_frequency(self):368 try:369 freq = self.dev.getFrequency(timeout=3)370 except dbus.DBusException:371 freq = 0.0372 # Hz -> GHz373 self._freq = freq / 1000000000.0374 return self._freq375 376 def get_ip_address(self):377 return self._ip_address378 379 def get_strength(self):380 return self._strength381 382 def set_strength(self, strength):383 if strength == self._strength:384 return False385 386 if strength >= 0 and strength <= 100:387 self._strength = strength388 else:389 self._strength = 0390 391 if self._valid:392 self.emit('strength-changed')393 394 def network_appeared(self, network):395 # NM may emit NetworkAppeared messages before the initialization-time396 # getProperties call completes. This means that we are in danger of397 # instantiating the "appeared" network here, and then instantiating398 # the same network later on when getProperties completes399 # (_update_reply_cb calls _update_networks).400 # We avoid this race by confirming that getProperties has completed401 # before listening to any NetworkAppeared messages. We assume that402 # any networks that get reported as appeared in this race window403 # will be included in the getProperties response.404 if not self._valid:405 return406 407 if self._networks.has_key(network):408 return409 net = Network(self._client, network)410 self._networks[network] = net411 net.connect('initialized', lambda *args:412 self._net_initialized_cb(None, *args))413 414 def network_disappeared(self, network):415 if not self._networks.has_key(network):416 return417 418 if self._valid:419 self.emit('network-disappeared', self._networks[network])420 421 del self._networks[network]422 423 def set_active_network(self, network):424 if self._active_network == network:425 return426 427 # Make sure the old one doesn't get a stuck state428 if self._active_network:429 self._active_network.set_state(NETWORK_STATE_NOTCONNECTED)430 self._active_network.disconnect(self._active_net_sigid)431 432 self._active_network = network433 434 if self._active_network:435 self._active_net_sigid = self._active_network.connect(436 "initialized", self._active_net_initialized)437 438 # don't emit ssid-changed for networks that are not yet valid439 if self._valid:440 if self._active_network and self._active_network.is_valid():441 self.emit('ssid-changed')442 elif not self._active_network:443 self.emit('ssid-changed')444 445 def _active_net_initialized(self, net, user_data=None):446 if self._active_network and self._active_network.is_valid():447 self.emit('ssid-changed')448 449 def _get_active_net_cb(self, state, net_op):450 if not self._networks.has_key(net_op):451 self.set_active_network(None)452 return453 454 self.set_active_network(self._networks[net_op])455 456 _device_to_network_state = {457 DEVICE_STATE_ACTIVATING : NETWORK_STATE_CONNECTING,458 DEVICE_STATE_ACTIVATED : NETWORK_STATE_CONNECTED,459 DEVICE_STATE_INACTIVE : NETWORK_STATE_NOTCONNECTED460 }461 462 network_state = _device_to_network_state[state]463 self._active_network.set_state(network_state)464 465 def _get_active_net_error_cb(self, err):466 logging.debug("Couldn't get active network: %s" % err)467 self.set_active_network(None)468 469 def get_state(self):470 return self._state471 472 def set_state(self, state):473 if state == self._state:474 return475 476 if state == DEVICE_STATE_INACTIVE:477 self._act_stage = 0478 479 self._state = state480 if self._valid:481 self.emit('state-changed')482 483 if self._type == DEVICE_TYPE_802_11_WIRELESS:484 if state == DEVICE_STATE_INACTIVE:485 self.set_active_network(None)486 else:487 self.dev.getActiveNetwork(488 reply_handler=lambda *args:489 self._get_active_net_cb(state, *args),490 error_handler=self._get_active_net_error_cb)491 492 if state == DEVICE_STATE_ACTIVATED:493 # 6248: reimplement for NM0.7494 # see http://dev.laptop.org/ticket/6248#comment:2495 self.dev.getProperties(496 reply_handler=self._getproperties_for_ip_only_reply_cb,497 error_handler=self._getproperties_for_ip_only_error_cb)498 499 def set_activation_stage(self, stage):500 if stage == self._act_stage:501 return502 self._act_stage = stage503 if self._valid:504 self.emit('activation-stage-changed')505 506 # 6248: reimplement for NM0.7507 # see http://dev.laptop.org/ticket/6248#comment:2508 self.dev.getProperties(509 reply_handler=self._getproperties_for_ip_only_reply_cb,510 error_handler=self._getproperties_for_ip_only_error_cb)511 512 def get_activation_stage(self):513 return self._act_stage514 515 def get_ssid(self):516 if self._active_network and self._active_network.is_valid():517 return self._active_network.get_ssid()518 elif not self._active_network:519 return None520 521 def get_active_network(self):522 return self._active_network523 524 def get_type(self):525 return self._type526 527 def is_valid(self):528 return self._valid529 530 def set_carrier(self, on):531 self._link = on532 533 def get_capabilities(self):534 return self._caps535 536 class NMClient(gobject.GObject):537 __gsignals__ = {538 'device-added' : (gobject.SIGNAL_RUN_FIRST,539 gobject.TYPE_NONE,540 ([gobject.TYPE_PYOBJECT])),541 'device-activated' : (gobject.SIGNAL_RUN_FIRST,542 gobject.TYPE_NONE,543 ([gobject.TYPE_PYOBJECT])),544 'device-activating': (gobject.SIGNAL_RUN_FIRST,545 gobject.TYPE_NONE,546 ([gobject.TYPE_PYOBJECT])),547 'device-removed' : (gobject.SIGNAL_RUN_FIRST,548 gobject.TYPE_NONE,549 ([gobject.TYPE_PYOBJECT]))550 }551 552 def __init__(self):553 gobject.GObject.__init__(self)554 555 self.nminfo = None556 self._nm_present = False557 self._nm_proxy = None558 self._nm_obj = None559 self._sig_handlers = None560 self._update_timer = 0561 self._devices = {}562 563 self.nminfo = nminfo.NMInfo(self)564 565 self._setup_dbus()566 if self._nm_present:567 self._get_initial_devices()568 569 def get_devices(self):570 return self._devices.values()571 572 def _get_initial_devices_reply_cb(self, ops):573 for op in ops:574 self._add_device(op)575 576 def _dev_initialized_cb(self, dev):577 self.emit('device-added', dev)578 579 def _dev_init_failed_cb(self, dev):580 # Device failed to initialize, likely due to dbus errors or something581 op = dev.get_op()582 self._remove_device(op)583 584 def _get_initial_devices_error_cb(self, err):585 logging.debug("Error updating devices (%s)" % err)586 587 def _get_initial_devices(self):588 self._nm_obj.getDevices(589 reply_handler=self._get_initial_devices_reply_cb,590 error_handler=self._get_initial_devices_error_cb)591 592 def _add_device(self, dev_op):593 if self._devices.has_key(dev_op):594 return595 dev = Device(self, dev_op)596 self._devices[dev_op] = dev597 dev.connect('init-failed', self._dev_init_failed_cb)598 dev.connect('initialized', self._dev_initialized_cb)599 dev.connect('state-changed', self._dev_state_changed_cb)600 601 def _remove_device(self, dev_op):602 if not self._devices.has_key(dev_op):603 return604 dev = self._devices[dev_op]605 if dev.is_valid():606 self.emit('device-removed', dev)607 del self._devices[dev_op]608 609 def _dev_state_changed_cb(self, dev):610 op = dev.get_op()611 if not self._devices.has_key(op) or not dev.is_valid():612 return613 if dev.get_state() == DEVICE_STATE_ACTIVATING:614 self.emit('device-activating', dev)615 elif dev.get_state() == DEVICE_STATE_ACTIVATED:616 self.emit('device-activated', dev)617 618 def get_device(self, dev_op):619 if not self._devices.has_key(dev_op):620 return None621 return self._devices[dev_op]622 623 def _setup_dbus(self):624 self._sig_handlers = {625 'StateChange': self.state_changed_sig_handler,626 'DeviceAdded': self.device_added_sig_handler,627 'DeviceRemoved': self.device_removed_sig_handler,628 'DeviceActivationStage': self.device_activation_stage_sig_handler,629 'DeviceActivating': self.device_activating_sig_handler,630 'DeviceNowActive': self.device_now_active_sig_handler,631 'DeviceNoLongerActive': self.device_no_longer_active_sig_handler,632 'DeviceActivationFailed': \633 self.device_activation_failed_sig_handler,634 'DeviceCarrierOn': self.device_carrier_on_sig_handler,635 'DeviceCarrierOff': self.device_carrier_off_sig_handler,636 'DeviceStrengthChanged': \637 self.wireless_device_strength_changed_sig_handler,638 'WirelessNetworkAppeared': \639 self.wireless_network_appeared_sig_handler,640 'WirelessNetworkDisappeared': \641 self.wireless_network_disappeared_sig_handler,642 'WirelessNetworkStrengthChanged': \643 self.wireless_network_strength_changed_sig_handler644 }645 646 try:647 self._nm_proxy = sys_bus.get_object(NM_SERVICE, NM_PATH,648 follow_name_owner_changes=True)649 self._nm_obj = dbus.Interface(self._nm_proxy, NM_IFACE)650 except dbus.DBusException, e:651 logging.debug("Could not connect to NetworkManager: %s" % e)652 self._nm_present = False653 return654 655 sys_bus.add_signal_receiver(self.name_owner_changed_sig_handler,656 signal_name="NameOwnerChanged",657 dbus_interface="org.freedesktop.DBus")658 659 for (signal, handler) in self._sig_handlers.items():660 sys_bus.add_signal_receiver(handler, signal_name=signal,661 dbus_interface=NM_IFACE)662 663 # Find out whether or not NMI is running664 try:665 bus_object = sys_bus.get_object('org.freedesktop.DBus',666 '/org/freedesktop/DBus')667 name_ = bus_object.GetNameOwner( \668 "org.freedesktop.NetworkManagerInfo",669 dbus_interface='org.freedesktop.DBus')670 self._nm_present = True671 except dbus.DBusException:672 self._nm_present = False673 674 def set_active_device(self, device, network=None,675 mesh_freq=None, mesh_start=None):676 ssid = ""677 if network:678 ssid = network.get_ssid()679 if device.get_type() == DEVICE_TYPE_802_11_MESH_OLPC:680 if mesh_freq or mesh_start:681 if mesh_freq and not mesh_start:682 self._nm_obj.setActiveDevice(device.get_op(),683 dbus.Double(mesh_freq))684 elif mesh_start and not mesh_freq:685 self._nm_obj.setActiveDevice(device.get_op(),686 dbus.Double(0.0),687 dbus.UInt32(mesh_start))688 else:689 self._nm_obj.setActiveDevice(device.get_op(),690 dbus.Double(mesh_freq),691 dbus.UInt32(mesh_start))692 else:693 self._nm_obj.setActiveDevice(device.get_op())694 else:695 self._nm_obj.setActiveDevice(device.get_op(), ssid)696 697 def state_changed_sig_handler(self, new_state):698 logging.debug('NM State Changed to %d' % new_state)699 700 def device_activation_stage_sig_handler(self, device, stage):701 logging.debug('Device Activation Stage "%s" for device %s'702 % (NM_DEVICE_STAGE_STRINGS[stage], device))703 if not self._devices.has_key(device):704 logging.debug('DeviceActivationStage, device %s does not exist'705 % (device))706 return707 self._devices[device].set_activation_stage(stage)708 709 def device_activating_sig_handler(self, device):710 logging.debug('DeviceActivating for %s' % (device))711 if not self._devices.has_key(device):712 logging.debug('DeviceActivating, device %s does not exist'713 % (device))714 return715 self._devices[device].set_state(DEVICE_STATE_ACTIVATING)716 717 def device_now_active_sig_handler(self, device, ssid=None):718 logging.debug('DeviceNowActive for %s' % (device))719 if not self._devices.has_key(device):720 logging.debug('DeviceNowActive, device %s does not exist'721 % (device))722 return723 self._devices[device].set_state(DEVICE_STATE_ACTIVATED)724 725 def device_no_longer_active_sig_handler(self, device):726 logging.debug('DeviceNoLongerActive for %s' % (device))727 if not self._devices.has_key(device):728 logging.debug('DeviceNoLongerActive, device %s does not exist'729 % (device))730 return731 self._devices[device].set_state(DEVICE_STATE_INACTIVE)732 733 def device_activation_failed_sig_handler(self, device, ssid=None):734 logging.debug('DeviceActivationFailed for %s' % (device))735 if not self._devices.has_key(device):736 logging.debug('DeviceActivationFailed, device %s does not exist'737 % (device))738 return739 self._devices[device].set_state(DEVICE_STATE_INACTIVE)740 741 def name_owner_changed_sig_handler(self, name, old, new):742 if name != NM_SERVICE:743 return744 if (old and len(old)) and (not new and not len(new)):745 # NM went away746 self._nm_present = False747 devs = self._devices.keys()748 for op in devs:749 self._remove_device(op)750 self._devices = {}751 elif (not old and not len(old)) and (new and len(new)):752 # NM started up753 self._nm_present = True754 self._get_initial_devices()755 756 def device_added_sig_handler(self, device):757 logging.debug('DeviceAdded for %s' % (device))758 self._add_device(device)759 760 def device_removed_sig_handler(self, device):761 logging.debug('DeviceRemoved for %s' % (device))762 self._remove_device(device)763 764 def wireless_network_appeared_sig_handler(self, device, network):765 if not self._devices.has_key(device):766 return767 self._devices[device].network_appeared(network)768 769 def wireless_network_disappeared_sig_handler(self, device, network):770 if not self._devices.has_key(device):771 return772 self._devices[device].network_disappeared(network)773 774 def wireless_device_strength_changed_sig_handler(self, device, strength):775 if not self._devices.has_key(device):776 return777 self._devices[device].set_strength(strength)778 779 def wireless_network_strength_changed_sig_handler(self, device,780 network, strength):781 if not self._devices.has_key(device):782 return783 net = self._devices[device].get_network(network)784 if net:785 net.set_strength(strength)786 787 def device_carrier_on_sig_handler(self, device):788 if not self._devices.has_key(device):789 return790 self._devices[device].set_carrier(True)791 792 def device_carrier_off_sig_handler(self, device):793 if not self._devices.has_key(device):794 return795 self._devices[device].set_carrier(False) -
deleted file src/hardware/nminfo.py
diff --git a/src/hardware/nminfo.py b/src/hardware/nminfo.py deleted file mode 100644 index 9f427e0..0000000
+ - 1 # vi: ts=4 ai noet2 #3 # Copyright (C) 2006-2007 Red Hat, Inc.4 #5 # This program is free software; you can redistribute it and/or modify6 # it under the terms of the GNU General Public License as published by7 # the Free Software Foundation; either version 2 of the License, or8 # (at your option) any later version.9 #10 # This program is distributed in the hope that it will be useful,11 # but WITHOUT ANY WARRANTY; without even the implied warranty of12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13 # GNU General Public License for more details.14 #15 # You should have received a copy of the GNU General Public License16 # along with this program; if not, write to the Free Software17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA18 19 import dbus20 import dbus.service21 import time22 import os23 import binascii24 import ConfigParser25 import logging26 27 import nmclient28 import keydialog29 import gtk30 from sugar import env31 32 IW_AUTH_KEY_MGMT_802_1X = 0x133 IW_AUTH_KEY_MGMT_PSK = 0x234 35 IW_AUTH_WPA_VERSION_DISABLED = 0x0000000136 IW_AUTH_WPA_VERSION_WPA = 0x0000000237 IW_AUTH_WPA_VERSION_WPA2 = 0x0000000438 39 NM_AUTH_TYPE_WPA_PSK_AUTO = 0x0000000040 IW_AUTH_CIPHER_NONE = 0x0000000141 IW_AUTH_CIPHER_WEP40 = 0x0000000242 IW_AUTH_CIPHER_TKIP = 0x0000000443 IW_AUTH_CIPHER_CCMP = 0x0000000844 IW_AUTH_CIPHER_WEP104 = 0x0000001045 46 IW_AUTH_ALG_OPEN_SYSTEM = 0x0000000147 IW_AUTH_ALG_SHARED_KEY = 0x0000000248 49 NM_INFO_IFACE = 'org.freedesktop.NetworkManagerInfo'50 NM_INFO_PATH = '/org/freedesktop/NetworkManagerInfo'51 52 53 class NoNetworks(dbus.DBusException):54 def __init__(self):55 dbus.DBusException.__init__(self)56 self._dbus_error_name = NM_INFO_IFACE + '.NoNetworks'57 58 class CanceledKeyRequestError(dbus.DBusException):59 def __init__(self):60 dbus.DBusException.__init__(self)61 self._dbus_error_name = NM_INFO_IFACE + '.CanceledError'62 63 64 class NetworkInvalidError(Exception):65 pass66 67 68 class NMConfig(ConfigParser.ConfigParser):69 def get_bool(self, section, name):70 opt = self.get(section, name)71 if type(opt) == str:72 if opt.lower() == 'yes' or opt.lower() == 'true':73 return True74 elif opt.lower() == 'no' or opt.lower() == 'false':75 return False76 raise ValueError("Invalid format for %s/%s. Should be one of" \77 " [yes, no, true, false]." % (section, name))78 79 def get_list(self, section, name):80 opt = self.get(section, name)81 if type(opt) != str or not len(opt):82 return []83 try:84 return opt.split()85 except Exception:86 raise ValueError("Invalid format for %s/%s. Should be a" \87 " space-separate list." % (section, name))88 89 def get_int(self, section, name):90 opt = self.get(section, name)91 try:92 return int(opt)93 except ValueError:94 raise ValueError("Invalid format for %s/%s. Should be a" \95 " valid integer." % (section, name))96 97 def get_float(self, section, name):98 opt = self.get(section, name)99 try:100 return float(opt)101 except ValueError:102 raise ValueError("Invalid format for %s/%s. Should be a" \103 " valid float." % (section, name))104 105 106 NETWORK_TYPE_UNKNOWN = 0107 NETWORK_TYPE_ALLOWED = 1108 NETWORK_TYPE_INVALID = 2109 110 111 class Security(object):112 def __init__(self, we_cipher):113 self._we_cipher = we_cipher114 self._key = None115 self._auth_alg = None116 117 def read_from_config(self, cfg, name):118 pass119 120 def read_from_args(self, args):121 pass122 123 def new_from_config(cfg, name):124 security = None125 we_cipher = cfg.get_int(name, "we_cipher")126 if we_cipher == IW_AUTH_CIPHER_NONE:127 security = Security(we_cipher)128 elif we_cipher == IW_AUTH_CIPHER_WEP40 or \129 we_cipher == IW_AUTH_CIPHER_WEP104:130 security = WEPSecurity(we_cipher)131 elif we_cipher == NM_AUTH_TYPE_WPA_PSK_AUTO or \132 we_cipher == IW_AUTH_CIPHER_CCMP or \133 we_cipher == IW_AUTH_CIPHER_TKIP:134 security = WPASecurity(we_cipher)135 else:136 raise ValueError("Unsupported security combo")137 security.read_from_config(cfg, name)138 return security139 new_from_config = staticmethod(new_from_config)140 141 def new_from_args(we_cipher, args):142 security = None143 try:144 if we_cipher == IW_AUTH_CIPHER_NONE:145 security = Security(we_cipher)146 elif we_cipher == IW_AUTH_CIPHER_WEP40 or \147 we_cipher == IW_AUTH_CIPHER_WEP104:148 security = WEPSecurity(we_cipher)149 elif we_cipher == NM_AUTH_TYPE_WPA_PSK_AUTO or \150 we_cipher == IW_AUTH_CIPHER_CCMP or \151 we_cipher == IW_AUTH_CIPHER_TKIP:152 security = WPASecurity(we_cipher)153 else:154 raise ValueError("Unsupported security combo")155 security.read_from_args(args)156 except ValueError, e:157 logging.debug("Error reading security information: %s" % e)158 del security159 return None160 return security161 new_from_args = staticmethod(new_from_args)162 163 def get_properties(self):164 return [dbus.Int32(self._we_cipher)]165 166 def write_to_config(self, section, config):167 config.set(section, "we_cipher", self._we_cipher)168 169 170 class WEPSecurity(Security):171 def read_from_args(self, args):172 if len(args) != 2:173 raise ValueError("not enough arguments")174 key = args[0]175 auth_alg = args[1]176 if isinstance(key, unicode):177 key = key.encode()178 if not isinstance(key, str):179 raise ValueError("wrong argument type for key")180 if not isinstance(auth_alg, int):181 raise ValueError("wrong argument type for auth_alg")182 self._key = key183 self._auth_alg = auth_alg184 185 def read_from_config(self, cfg, name):186 # Key should be a hex encoded string187 self._key = cfg.get(name, "key")188 if self._we_cipher == IW_AUTH_CIPHER_WEP40 and len(self._key) != 10:189 raise ValueError("Key length not right for 40-bit WEP")190 if self._we_cipher == IW_AUTH_CIPHER_WEP104 and len(self._key) != 26:191 raise ValueError("Key length not right for 104-bit WEP")192 193 try:194 binascii.a2b_hex(self._key)195 except TypeError:196 raise ValueError("Key was not a hexadecimal string.")197 198 self._auth_alg = cfg.get_int(name, "auth_alg")199 if self._auth_alg != IW_AUTH_ALG_OPEN_SYSTEM and \200 self._auth_alg != IW_AUTH_ALG_SHARED_KEY:201 raise ValueError("Invalid authentication algorithm %d"202 % self._auth_alg)203 204 def get_properties(self):205 args = Security.get_properties(self)206 args.append(dbus.String(self._key))207 args.append(dbus.Int32(self._auth_alg))208 return args209 210 def write_to_config(self, section, config):211 Security.write_to_config(self, section, config)212 config.set(section, "key", self._key)213 config.set(section, "auth_alg", self._auth_alg)214 215 class WPASecurity(Security):216 def __init__(self, we_cipher):217 Security.__init__(self, we_cipher)218 self._wpa_ver = None219 self._key_mgmt = None220 221 def read_from_args(self, args):222 if len(args) != 3:223 raise ValueError("not enough arguments")224 key = args[0]225 if isinstance(key, unicode):226 key = key.encode()227 if not isinstance(key, str):228 raise ValueError("wrong argument type for key")229 230 wpa_ver = args[1]231 if not isinstance(wpa_ver, int):232 raise ValueError("wrong argument type for WPA version")233 234 key_mgmt = args[2]235 if not isinstance(key_mgmt, int):236 raise ValueError("wrong argument type for WPA key management")237 if not key_mgmt & IW_AUTH_KEY_MGMT_PSK:238 raise ValueError("Key management types other than" \239 " PSK are not supported")240 241 self._key = key242 self._wpa_ver = wpa_ver243 self._key_mgmt = key_mgmt244 245 def read_from_config(self, cfg, name):246 # Key should be a hex encoded string247 self._key = cfg.get(name, "key")248 if len(self._key) != 64:249 raise ValueError("Key length not right for WPA-PSK")250 251 try:252 binascii.a2b_hex(self._key)253 except TypeError:254 raise ValueError("Key was not a hexadecimal string.")255 256 self._wpa_ver = cfg.get_int(name, "wpa_ver")257 if self._wpa_ver != IW_AUTH_WPA_VERSION_WPA and \258 self._wpa_ver != IW_AUTH_WPA_VERSION_WPA2:259 raise ValueError("Invalid WPA version %d" % self._wpa_ver)260 261 self._key_mgmt = cfg.get_int(name, "key_mgmt")262 if not self._key_mgmt & IW_AUTH_KEY_MGMT_PSK:263 raise ValueError("Invalid WPA key management option %d"264 % self._key_mgmt)265 266 def get_properties(self):267 args = Security.get_properties(self)268 args.append(dbus.String(self._key))269 args.append(dbus.Int32(self._wpa_ver))270 args.append(dbus.Int32(self._key_mgmt))271 return args272 273 def write_to_config(self, section, config):274 Security.write_to_config(self, section, config)275 config.set(section, "key", self._key)276 config.set(section, "wpa_ver", self._wpa_ver)277 config.set(section, "key_mgmt", self._key_mgmt)278 279 280 class Network:281 def __init__(self, ssid):282 self.ssid = ssid283 self.timestamp = int(time.time())284 self.bssids = []285 self.we_cipher = 0286 self._security = None287 288 def get_properties(self):289 bssid_list = dbus.Array([], signature="s")290 for item in self.bssids:291 bssid_list.append(dbus.String(item))292 args = [dbus.String(self.ssid), dbus.Int32(self.timestamp),293 dbus.Boolean(True), bssid_list]294 args += self._security.get_properties()295 return tuple(args)296 297 def get_security(self):298 return self._security.get_properties()299 300 def set_security(self, security):301 self._security = security302 303 def read_from_args(self, auto, bssid, we_cipher, args):304 if auto == False:305 self.timestamp = int(time.time())306 if not bssid in self.bssids:307 self.bssids.append(bssid)308 309 self._security = Security.new_from_args(we_cipher, args)310 if not self._security:311 raise NetworkInvalidError("Invalid security information")312 313 def read_from_config(self, config):314 try:315 self.timestamp = config.get_int(self.ssid, "timestamp")316 except (ConfigParser.NoOptionError, ValueError), e:317 raise NetworkInvalidError(e)318 319 try:320 self._security = Security.new_from_config(config, self.ssid)321 except Exception, e:322 raise NetworkInvalidError(e)323 324 # The following don't need to be present325 try:326 self.bssids = config.get_list(self.ssid, "bssids")327 except (ConfigParser.NoOptionError, ValueError), e:328 logging.debug("Error reading bssids: %s" % e)329 330 def write_to_config(self, config):331 try:332 config.add_section(self.ssid)333 config.set(self.ssid, "timestamp", self.timestamp)334 if len(self.bssids) > 0:335 opt = " "336 opt = opt.join(self.bssids)337 config.set(self.ssid, "bssids", opt)338 self._security.write_to_config(self.ssid, config)339 except Exception, e:340 logging.debug("Error writing '%s': %s" % (self.ssid, e))341 342 343 class NotFoundError(dbus.DBusException):344 pass345 class UnsupportedError(dbus.DBusException):346 pass347 348 class NMInfoDBusServiceHelper(dbus.service.Object):349 def __init__(self, parent):350 self._parent = parent351 bus = dbus.SystemBus()352 353 # If NMI is already around, don't grab the NMI service354 bus_object = bus.get_object('org.freedesktop.DBus',355 '/org/freedesktop/DBus')356 name = None357 try:358 name = bus_object.GetNameOwner( \359 "org.freedesktop.NetworkManagerInfo",360 dbus_interface='org.freedesktop.DBus')361 except dbus.DBusException:362 logging.debug("Error getting owner of NMI")363 if name:364 logging.info("NMI service already owned by %s, won't claim it."365 % name)366 367 bus_name = dbus.service.BusName(NM_INFO_IFACE, bus=bus)368 dbus.service.Object.__init__(self, bus_name, NM_INFO_PATH)369 370 @dbus.service.method(NM_INFO_IFACE, in_signature='i', out_signature='as')371 def getNetworks(self, net_type):372 ssids = self._parent.get_networks(net_type)373 if len(ssids) > 0:374 return dbus.Array(ssids)375 376 raise NoNetworks()377 378 @dbus.service.method(NM_INFO_IFACE, in_signature='si',379 async_callbacks=('async_cb', 'async_err_cb'))380 def getNetworkProperties(self, ssid, net_type, async_cb, async_err_cb):381 self._parent.get_network_properties(ssid, net_type,382 async_cb, async_err_cb)383 384 @dbus.service.method(NM_INFO_IFACE)385 def updateNetworkInfo(self, ssid, bauto, bssid, cipher, *args):386 self._parent.update_network_info(ssid, bauto, bssid, cipher, args)387 388 @dbus.service.method(NM_INFO_IFACE,389 async_callbacks=('async_cb', 'async_err_cb'))390 def getKeyForNetwork(self, dev_path, net_path, ssid, attempt,391 new_key, async_cb, async_err_cb):392 self._parent.get_key_for_network(dev_path, net_path, ssid,393 attempt, new_key, async_cb, async_err_cb)394 395 @dbus.service.method(NM_INFO_IFACE)396 def cancelGetKeyForNetwork(self):397 self._parent.cancel_get_key_for_network()398 399 class NMInfo(object):400 def __init__(self, client):401 profile_path = env.get_profile_path()402 self._cfg_file = os.path.join(profile_path, "nm", "networks.cfg")403 self._nmclient = client404 self._allowed_networks = self._read_config()405 self._dbus_helper = NMInfoDBusServiceHelper(self)406 self._key_dialog = None407 408 def save_config(self):409 self._write_config(self._allowed_networks)410 411 def _read_config(self):412 if not os.path.exists(os.path.dirname(self._cfg_file)):413 os.makedirs(os.path.dirname(self._cfg_file), 0755)414 if not os.path.exists(self._cfg_file):415 self._write_config({})416 return {}417 418 config = NMConfig()419 config.read(self._cfg_file)420 networks = {}421 for name in config.sections():422 try:423 net = Network(name)424 net.read_from_config(config)425 networks[name] = net426 except Exception, e:427 logging.error("Error when processing config for" \428 " the network %s: %r" % (name, e))429 430 del config431 return networks432 433 def _write_config(self, networks):434 fp = open(self._cfg_file, 'w')435 config = NMConfig()436 for net in networks.values():437 net.write_to_config(config)438 config.write(fp)439 fp.close()440 del config441 442 def get_networks(self, net_type):443 if net_type != NETWORK_TYPE_ALLOWED:444 raise ValueError("Bad network type")445 nets = []446 for net in self._allowed_networks.values():447 nets.append(net.ssid)448 logging.debug("Returning networks: %s" % nets)449 return nets450 451 def get_network_properties(self, ssid, net_type, async_cb, async_err_cb):452 if not isinstance(ssid, unicode):453 async_err_cb(ValueError("Invalid arguments; ssid must be unicode."))454 if net_type != NETWORK_TYPE_ALLOWED:455 async_err_cb(ValueError("Bad network type"))456 if not self._allowed_networks.has_key(ssid):457 async_err_cb(NotFoundError("Network '%s' not found." % ssid))458 network = self._allowed_networks[ssid]459 props = network.get_properties()460 461 # DBus workaround: the normal method return handler wraps462 # the returned arguments in a tuple and then converts that to a463 # struct, but NetworkManager expects a plain list of arguments.464 # It turns out that the async callback method return code _doesn't_465 # wrap the returned arguments in a tuple, so as a workaround use466 # the async callback stuff here even though we're not doing it467 # asynchronously.468 async_cb(*props)469 470 def update_network_info(self, ssid, auto, bssid, we_cipher, args):471 if not isinstance(ssid, unicode):472 raise ValueError("Invalid arguments; ssid must be unicode.")473 if self._allowed_networks.has_key(ssid):474 del self._allowed_networks[ssid]475 net = Network(ssid)476 try:477 net.read_from_args(auto, bssid, we_cipher, args)478 logging.debug("Updated network information for '%s'." % ssid)479 self._allowed_networks[ssid] = net480 self.save_config()481 except NetworkInvalidError, e:482 logging.debug("Error updating network information: %s" % e)483 del net484 485 def get_key_for_network(self, dev_op, net_op, ssid, attempt,486 new_key, async_cb, async_err_cb):487 if not isinstance(ssid, unicode):488 raise ValueError("Invalid arguments; ssid must be unicode.")489 if self._allowed_networks.has_key(ssid) and not new_key:490 # We've got the info already491 net = self._allowed_networks[ssid]492 async_cb(tuple(net.get_security()))493 return494 495 # Otherwise, ask the user for it496 net = None497 dev = self._nmclient.get_device(dev_op)498 if not dev:499 async_err_cb(NotFoundError("Device was unknown."))500 return501 502 if dev.get_type() == nmclient.DEVICE_TYPE_802_3_ETHERNET:503 # We don't support wired 802.1x yet...504 async_err_cb(UnsupportedError("Device type is unsupported by NMI."))505 return506 507 net = dev.get_network(net_op)508 if not net:509 async_err_cb(NotFoundError("Network was unknown."))510 return511 512 self._key_dialog = keydialog.new_key_dialog(net, async_cb, async_err_cb)513 self._key_dialog.connect("response", self._key_dialog_response_cb)514 self._key_dialog.connect("destroy", self._key_dialog_destroy_cb)515 self._key_dialog.show_all()516 517 def _key_dialog_destroy_cb(self, widget, data=None):518 if widget != self._key_dialog:519 return520 self._key_dialog_response_cb(widget, gtk.RESPONSE_CANCEL)521 522 def _key_dialog_response_cb(self, widget, response_id):523 if widget != self._key_dialog:524 return525 526 (async_cb, async_err_cb) = self._key_dialog.get_callbacks()527 security = None528 if response_id == gtk.RESPONSE_OK:529 security = self._key_dialog.create_security()530 self._key_dialog = None531 widget.destroy()532 533 if response_id in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_NONE]:534 # key dialog dialog was canceled; send the error back to NM535 async_err_cb(CanceledKeyRequestError())536 elif response_id == gtk.RESPONSE_OK:537 if not security:538 raise RuntimeError("Invalid security arguments.")539 props = security.get_properties()540 a = tuple(props)541 async_cb(*a)542 else:543 raise RuntimeError("Unhandled key dialog response %d" % response_id)544 545 def cancel_get_key_for_network(self):546 # Close the wireless key dialog and just have it return547 # with the 'canceled' argument set to true548 if not self._key_dialog:549 return550 self._key_dialog_destroy_cb(self._key_dialog)551 552 # this method is invoked directly in-process (not by DBus).553 def delete_all_networks(self):554 self._allowed_networks = {}555 self.save_config()556 -
src/model/Makefile.am
diff --git a/src/model/Makefile.am b/src/model/Makefile.am index 0b7d14c..c89ce47 100644
a b SUBDIRS = devices 3 3 sugardir = $(pkgdatadir)/shell/model 4 4 sugar_PYTHON = \ 5 5 __init__.py \ 6 accesspointmodel.py \7 6 BuddyModel.py \ 8 7 Friends.py \ 9 8 Invites.py \ 10 9 Owner.py \ 11 MeshModel.py \12 10 shellmodel.py \ 13 11 homeactivity.py \ 14 homemodel.py 12 homemodel.py \ 13 network.py \ 14 neighborhood.py -
deleted file src/model/MeshModel.py
diff --git a/src/model/MeshModel.py b/src/model/MeshModel.py deleted file mode 100644 index fa33035..0000000
+ - 1 # Copyright (C) 2006-2007 Red Hat, Inc.2 #3 # This program is free software; you can redistribute it and/or modify4 # it under the terms of the GNU General Public License as published by5 # the Free Software Foundation; either version 2 of the License, or6 # (at your option) any later version.7 #8 # This program is distributed in the hope that it will be useful,9 # but WITHOUT ANY WARRANTY; without even the implied warranty of10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11 # GNU General Public License for more details.12 #13 # You should have received a copy of the GNU General Public License14 # along with this program; if not, write to the Free Software15 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA16 17 import gobject18 19 from sugar.graphics.xocolor import XoColor20 from sugar.presence import presenceservice21 from sugar import activity22 23 from model.BuddyModel import BuddyModel24 from model.accesspointmodel import AccessPointModel25 from hardware import hardwaremanager26 from hardware import nmclient27 28 class ActivityModel:29 def __init__(self, act, bundle):30 self.activity = act31 self.bundle = bundle32 33 def get_id(self):34 return self.activity.props.id35 36 def get_icon_name(self):37 return self.bundle.icon38 39 def get_color(self):40 return XoColor(self.activity.props.color)41 42 def get_bundle_id(self):43 return self.bundle.bundle_id44 45 class MeshModel(gobject.GObject):46 __gsignals__ = {47 'activity-added': (gobject.SIGNAL_RUN_FIRST,48 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),49 'activity-removed': (gobject.SIGNAL_RUN_FIRST,50 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),51 'buddy-added': (gobject.SIGNAL_RUN_FIRST,52 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),53 'buddy-moved': (gobject.SIGNAL_RUN_FIRST,54 gobject.TYPE_NONE,55 ([gobject.TYPE_PYOBJECT,56 gobject.TYPE_PYOBJECT])),57 'buddy-removed': (gobject.SIGNAL_RUN_FIRST,58 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),59 'access-point-added': (gobject.SIGNAL_RUN_FIRST,60 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),61 'access-point-removed': (gobject.SIGNAL_RUN_FIRST,62 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),63 'mesh-added': (gobject.SIGNAL_RUN_FIRST,64 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),65 'mesh-removed': (gobject.SIGNAL_RUN_FIRST,66 gobject.TYPE_NONE, ([]))67 }68 69 def __init__(self):70 gobject.GObject.__init__(self)71 72 self._activities = {}73 self._buddies = {}74 self._access_points = {}75 self._mesh = None76 77 self._pservice = presenceservice.get_instance()78 self._pservice.connect("activity-appeared",79 self._activity_appeared_cb)80 self._pservice.connect('activity-disappeared',81 self._activity_disappeared_cb)82 self._pservice.connect("buddy-appeared",83 self._buddy_appeared_cb)84 self._pservice.connect("buddy-disappeared",85 self._buddy_disappeared_cb)86 87 # Add any buddies the PS knows about already88 self._pservice.get_buddies_async(reply_handler=self._get_buddies_cb)89 90 self._pservice.get_activities_async(91 reply_handler=self._get_activities_cb)92 93 network_manager = hardwaremanager.get_network_manager()94 if network_manager:95 for nm_device in network_manager.get_devices():96 self._add_network_device(nm_device)97 network_manager.connect('device-added',98 self._nm_device_added_cb)99 network_manager.connect('device-removed',100 self._nm_device_removed_cb)101 102 def _get_buddies_cb(self, buddy_list):103 for buddy in buddy_list:104 self._buddy_appeared_cb(self._pservice, buddy)105 106 def _get_activities_cb(self, activity_list):107 for act in activity_list:108 self._check_activity(act)109 110 def _nm_device_added_cb(self, manager, nm_device):111 self._add_network_device(nm_device)112 113 def _nm_device_removed_cb(self, manager, nm_device):114 self._remove_network_device(nm_device)115 116 def _nm_network_appeared_cb(self, nm_device, nm_network):117 self._add_access_point(nm_device, nm_network)118 119 def _nm_network_disappeared_cb(self, nm_device, nm_network):120 if self._access_points.has_key(nm_network.get_op()):121 ap = self._access_points[nm_network.get_op()]122 self._remove_access_point(ap)123 124 def _add_network_device(self, nm_device):125 dtype = nm_device.get_type()126 if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS:127 for nm_network in nm_device.get_networks():128 self._add_access_point(nm_device, nm_network)129 130 nm_device.connect('network-appeared',131 self._nm_network_appeared_cb)132 nm_device.connect('network-disappeared',133 self._nm_network_disappeared_cb)134 elif dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC:135 self._mesh = nm_device136 self.emit('mesh-added', self._mesh)137 138 def _remove_network_device(self, nm_device):139 if nm_device == self._mesh:140 self._mesh = None141 self.emit('mesh-removed')142 elif nm_device.get_type() == nmclient.DEVICE_TYPE_802_11_WIRELESS:143 aplist = self._access_points.values()144 for ap in aplist:145 if ap.get_nm_device() == nm_device:146 self._remove_access_point(ap)147 148 def _add_access_point(self, nm_device, nm_network):149 model = AccessPointModel(nm_device, nm_network)150 self._access_points[model.get_id()] = model151 self.emit('access-point-added', model)152 153 def _remove_access_point(self, ap):154 if not self._access_points.has_key(ap.get_id()):155 return156 self.emit('access-point-removed', ap)157 del self._access_points[ap.get_id()]158 159 def get_mesh(self):160 return self._mesh161 162 def get_access_points(self):163 return self._access_points.values()164 165 def get_activities(self):166 return self._activities.values()167 168 def get_buddies(self):169 return self._buddies.values()170 171 def _buddy_activity_changed_cb(self, model, cur_activity):172 if not self._buddies.has_key(model.get_key()):173 return174 if cur_activity and self._activities.has_key(cur_activity.props.id):175 activity_model = self._activities[cur_activity.props.id]176 self.emit('buddy-moved', model, activity_model)177 else:178 self.emit('buddy-moved', model, None)179 180 def _buddy_appeared_cb(self, pservice, buddy):181 if self._buddies.has_key(buddy.props.key):182 return183 184 model = BuddyModel(buddy=buddy)185 model.connect('current-activity-changed',186 self._buddy_activity_changed_cb)187 self._buddies[buddy.props.key] = model188 self.emit('buddy-added', model)189 190 cur_activity = buddy.props.current_activity191 if cur_activity:192 self._buddy_activity_changed_cb(model, cur_activity)193 194 def _buddy_disappeared_cb(self, pservice, buddy):195 if not self._buddies.has_key(buddy.props.key):196 return197 self.emit('buddy-removed', self._buddies[buddy.props.key])198 del self._buddies[buddy.props.key]199 200 def _activity_appeared_cb(self, pservice, act):201 self._check_activity(act)202 203 def _check_activity(self, presence_activity):204 registry = activity.get_registry()205 bundle = registry.get_activity(presence_activity.props.type)206 if not bundle:207 return208 if self.has_activity(presence_activity.props.id):209 return210 self.add_activity(bundle, presence_activity)211 212 def has_activity(self, activity_id):213 return self._activities.has_key(activity_id)214 215 def get_activity(self, activity_id):216 if self.has_activity(activity_id):217 return self._activities[activity_id]218 else:219 return None220 221 def add_activity(self, bundle, act):222 model = ActivityModel(act, bundle)223 self._activities[model.get_id()] = model224 self.emit('activity-added', model)225 226 for buddy in self._pservice.get_buddies():227 cur_activity = buddy.props.current_activity228 key = buddy.props.key229 if cur_activity == activity and self._buddies.has_key(key):230 buddy_model = self._buddies[key]231 self.emit('buddy-moved', buddy_model, model)232 233 def _activity_disappeared_cb(self, pservice, act):234 if self._activities.has_key(act.props.id):235 activity_model = self._activities[act.props.id]236 self.emit('activity-removed', activity_model)237 del self._activities[act.props.id] -
deleted file src/model/accesspointmodel.py
diff --git a/src/model/accesspointmodel.py b/src/model/accesspointmodel.py deleted file mode 100644 index f464f75..0000000
+ - 1 # Copyright (C) 2006-2007 Red Hat, Inc.2 #3 # This program is free software; you can redistribute it and/or modify4 # it under the terms of the GNU General Public License as published by5 # the Free Software Foundation; either version 2 of the License, or6 # (at your option) any later version.7 #8 # This program is distributed in the hope that it will be useful,9 # but WITHOUT ANY WARRANTY; without even the implied warranty of10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11 # GNU General Public License for more details.12 #13 # You should have received a copy of the GNU General Public License14 # along with this program; if not, write to the Free Software15 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA16 17 import gobject18 19 from hardware import nmclient20 21 STATE_CONNECTING = 022 STATE_CONNECTED = 123 STATE_NOTCONNECTED = 224 25 _nm_state_to_state = {26 nmclient.NETWORK_STATE_CONNECTED : STATE_CONNECTED,27 nmclient.NETWORK_STATE_CONNECTING : STATE_CONNECTING,28 nmclient.NETWORK_STATE_NOTCONNECTED : STATE_NOTCONNECTED29 }30 31 class AccessPointModel(gobject.GObject):32 __gproperties__ = {33 'name' : (str, None, None, None,34 gobject.PARAM_READABLE),35 'strength' : (int, None, None, 0, 100, 0,36 gobject.PARAM_READABLE),37 'state' : (int, None, None, STATE_CONNECTING,38 STATE_NOTCONNECTED, 0, gobject.PARAM_READABLE),39 'capabilities' : (int, None, None, 0, 0x7FFFFFFF, 0,40 gobject.PARAM_READABLE),41 'mode' : (int, None, None, 0, 6, 0, gobject.PARAM_READABLE)42 }43 44 def __init__(self, nm_device, nm_network):45 gobject.GObject.__init__(self)46 self._nm_network = nm_network47 self._nm_device = nm_device48 49 self._nm_network.connect('strength-changed',50 self._strength_changed_cb)51 self._nm_network.connect('state-changed',52 self._state_changed_cb)53 54 def _strength_changed_cb(self, nm_network):55 self.notify('strength')56 57 def _state_changed_cb(self, nm_network):58 self.notify('state')59 60 def get_id(self):61 return self._nm_network.get_op()62 63 def get_nm_device(self):64 return self._nm_device65 66 def get_nm_network(self):67 return self._nm_network68 69 def do_get_property(self, pspec):70 if pspec.name == 'strength':71 return self._nm_network.get_strength()72 elif pspec.name == 'name':73 return self._nm_network.get_ssid()74 elif pspec.name == 'state':75 nm_state = self._nm_network.get_state()76 return _nm_state_to_state[nm_state]77 elif pspec.name == 'capabilities':78 return self._nm_network.get_caps()79 elif pspec.name == 'mode':80 return self._nm_network.get_mode() -
src/model/devices/device.py
diff --git a/src/model/devices/device.py b/src/model/devices/device.py index 3273da9..6a62088 100644
a b 16 16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 17 18 18 import gobject 19 from hardware import nmclient20 19 21 20 from sugar import util 22 21 23 STATE_ACTIVATING = 024 STATE_ACTIVATED = 125 STATE_INACTIVE = 226 27 nm_state_to_state = {28 nmclient.DEVICE_STATE_ACTIVATING : STATE_ACTIVATING,29 nmclient.DEVICE_STATE_ACTIVATED : STATE_ACTIVATED,30 nmclient.DEVICE_STATE_INACTIVE : STATE_INACTIVE31 }32 33 22 class Device(gobject.GObject): 34 23 def __init__(self, device_id=None): 35 24 gobject.GObject.__init__(self) -
src/model/devices/devicesmodel.py
diff --git a/src/model/devices/devicesmodel.py b/src/model/devices/devicesmodel.py index f328109..aa9446c 100644
a b import logging 19 19 import gobject 20 20 import dbus 21 21 22 from model.devices import device23 22 from model.devices.network import wireless 24 from model.devices.network import mesh25 23 from model.devices import battery 26 24 from model.devices import speaker 27 from hardware import hardwaremanager 28 from hardware import nmclient 25 from model import network 26 27 _NM_SERVICE = 'org.freedesktop.NetworkManager' 28 _NM_IFACE = 'org.freedesktop.NetworkManager' 29 _NM_PATH = '/org/freedesktop/NetworkManager' 30 _NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' 29 31 30 32 class DevicesModel(gobject.GObject): 31 33 __gsignals__ = { … … class DevicesModel(gobject.GObject): 39 41 40 42 def __init__(self): 41 43 gobject.GObject.__init__(self) 44 self._bus = dbus.SystemBus() 45 self._netmgr = None 42 46 43 47 self._devices = {} 44 48 self._sigids = {} … … class DevicesModel(gobject.GObject): 62 66 self.add_device(battery.Device(udi)) 63 67 64 68 def _observe_network_manager(self): 65 network_manager = hardwaremanager.get_network_manager() 66 if not network_manager: 69 try: 70 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) 71 self._netmgr = dbus.Interface(obj, _NM_IFACE) 72 except dbus.DBusException: 73 logging.debug('%s service not available', _NM_SERVICE) 67 74 return 68 75 69 for dev in network_manager.get_devices(): 70 self._check_network_device(dev) 71 72 network_manager.connect('device-added', 73 self._network_device_added_cb) 74 network_manager.connect('device-activating', 75 self._network_device_activating_cb) 76 network_manager.connect('device-activated', 77 self._network_device_activated_cb) 78 network_manager.connect('device-removed', 79 self._network_device_removed_cb) 80 81 def _network_device_added_cb(self, network_manager, nm_device): 82 state = nm_device.get_state() 83 if state == nmclient.DEVICE_STATE_ACTIVATING \ 84 or state == nmclient.DEVICE_STATE_ACTIVATED: 85 self._check_network_device(nm_device) 86 87 def _network_device_activating_cb(self, network_manager, nm_device): 88 self._check_network_device(nm_device) 89 90 def _network_device_activated_cb(self, network_manager, nm_device): 91 pass 92 93 def _network_device_removed_cb(self, network_manager, nm_device): 94 if self._devices.has_key(str(nm_device.get_op())): 95 self.remove_device(self._get_network_device(nm_device)) 96 97 def _check_network_device(self, nm_device): 98 if not nm_device.is_valid(): 99 logging.debug("Device %s not valid" % nm_device.get_op()) 100 return 76 self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb, 77 error_handler=self.__get_devices_error_cb) 101 78 102 dtype = nm_device.get_type() 103 if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS \ 104 or dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC: 105 self._add_network_device(nm_device) 79 self._bus.add_signal_receiver(self.__device_added_cb, 80 signal_name='DeviceAdded', 81 dbus_interface=_NM_IFACE) 82 self._bus.add_signal_receiver(self.__device_removed_cb, 83 signal_name='DeviceRemoved', 84 dbus_interface=_NM_IFACE) 106 85 107 def _get_network_device(self, nm_device): 108 return self._devices[str(nm_device.get_op())] 86 def __get_devices_reply_cb(self, devices_o): 87 for dev_o in devices_o: 88 self._check_device(dev_o) 109 89 110 def _network_device_state_changed_cb(self, dev, param): 111 if dev.props.state == device.STATE_INACTIVE: 112 self.remove_device(dev) 90 def __get_devices_error_cb(self, err): 91 logging.error('Failed to get devices: %s', err) 113 92 114 def _add_network_device(self, nm_device): 115 if self._devices.has_key(str(nm_device.get_op())): 116 logging.debug("Tried to add device %s twice" % nm_device.get_op()) 117 return 93 def _check_device(self, device_o): 94 nm_device = self._bus.get_object(_NM_SERVICE, device_o) 95 props = dbus.Interface(nm_device, 'org.freedesktop.DBus.Properties') 96 97 device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') 98 if device_type == network.DEVICE_TYPE_802_11_WIRELESS: 99 device = wireless.Device(nm_device) 100 self.add_device(device) 101 102 def __device_added_cb(self, device_o): 103 self._check_device(device_o) 118 104 119 dtype = nm_device.get_type() 120 if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS: 121 dev = wireless.Device(nm_device) 122 self.add_device(dev) 123 sigid = dev.connect('notify::state', 124 self._network_device_state_changed_cb) 125 self._sigids[dev] = sigid 126 if dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC: 127 dev = mesh.Device(nm_device) 128 self.add_device(dev) 129 sigid = dev.connect('notify::state', 130 self._network_device_state_changed_cb) 131 self._sigids[dev] = sigid 105 def __device_removed_cb(self, device_o): 106 if device_o in self._devices: 107 device = self._devices[device_o] 108 self.remove_device(device) 132 109 133 110 def __iter__(self): 134 111 return iter(self._devices.values()) … … class DevicesModel(gobject.GObject): 139 116 140 117 def remove_device(self, dev): 141 118 self.emit('device-disappeared', self._devices[dev.get_id()]) 142 dev.disconnect(self._sigids[dev]) 143 del self._sigids[dev] 119 if dev in self._sigids: 120 dev.disconnect(self._sigids[dev]) 121 del self._sigids[dev] 144 122 del self._devices[dev.get_id()] -
src/model/devices/network/wireless.py
diff --git a/src/model/devices/network/wireless.py b/src/model/devices/network/wireless.py index b2efb49..e8b64ff 100644
a b 15 15 # along with this program; if not, write to the Free Software 16 16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 17 18 import gobject19 20 18 from model.devices import device 21 19 22 def freq_to_channel(freq):23 ftoc = { 2.412: 1, 2.417: 2, 2.422: 3, 2.427: 4,24 2.432: 5, 2.437: 6, 2.442: 7, 2.447: 8,25 2.452: 9, 2.457: 10, 2.462: 11, 2.467: 12,26 2.472: 1327 }28 return ftoc[freq]29 30 def channel_to_freq(channel):31 ctof = { 1: 2.412, 2: 2.417, 3: 2.422, 4: 2.427,32 5: 2.432, 6: 2.437, 7: 2.442, 8: 2.447,33 9: 2.452, 10: 2.457, 11: 2.462, 12: 2.467,34 13: 2.47235 }36 return ctof[channel]37 38 20 class Device(device.Device): 39 __gproperties__ = {40 'name' : (str, None, None, None,41 gobject.PARAM_READABLE),42 'strength' : (int, None, None, 0, 100, 0,43 gobject.PARAM_READABLE),44 'state' : (int, None, None, device.STATE_ACTIVATING,45 device.STATE_INACTIVE, 0, gobject.PARAM_READABLE),46 'frequency': (float, None, None, 0.0, 9999.99, 0.0,47 gobject.PARAM_READABLE),48 'ip-address' : (str, None, None, None, gobject.PARAM_READABLE),49 }50 51 21 def __init__(self, nm_device): 52 22 device.Device.__init__(self) 53 self._nm_device = nm_device 54 55 self._nm_device.connect('strength-changed', 56 self._strength_changed_cb) 57 self._nm_device.connect('ssid-changed', 58 self._ssid_changed_cb) 59 self._nm_device.connect('state-changed', 60 self._state_changed_cb) 61 self._nm_device.connect('ip-changed', self._ip_changed_cb) 62 63 def _strength_changed_cb(self, nm_device): 64 self.notify('strength') 65 66 def _ssid_changed_cb(self, nm_device): 67 self.notify('name') 68 69 def _state_changed_cb(self, nm_device): 70 self.notify('state') 71 72 def _ip_changed_cb(self, nm_device): 73 self.notify('ip-address') 74 75 def do_get_property(self, pspec): 76 if pspec.name == 'strength': 77 return self._nm_device.get_strength() 78 elif pspec.name == 'name': 79 import logging 80 logging.debug('wireless.Device.props.name: %s' % 81 self._nm_device.get_ssid()) 82 return self._nm_device.get_ssid() 83 elif pspec.name == 'state': 84 nm_state = self._nm_device.get_state() 85 return device.nm_state_to_state[nm_state] 86 elif pspec.name == 'frequency': 87 return self._nm_device.get_frequency() 88 elif pspec.name == 'ip-address': 89 return self._nm_device.get_ip_address() 23 self.nm_device = nm_device 90 24 91 25 def get_type(self): 92 26 return 'network.wireless' 93 27 94 28 def get_id(self): 95 return str(self._nm_device.get_op()) 96 97 def get_active_network_colors(self): 98 net = self._nm_device.get_active_network() 99 if not net: 100 return (None, None) 101 return net.get_colors() 29 return str(self.nm_device.object_path) 102 30 -
new file src/model/neighborhood.py
diff --git a/src/model/neighborhood.py b/src/model/neighborhood.py new file mode 100644 index 0000000..0a09a62
- + 1 # Copyright (C) 2006-2007 Red Hat, Inc. 2 # 3 # This program is free software; you can redistribute it and/or modify 4 # it under the terms of the GNU General Public License as published by 5 # the Free Software Foundation; either version 2 of the License, or 6 # (at your option) any later version. 7 # 8 # This program is distributed in the hope that it will be useful, 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # GNU General Public License for more details. 12 # 13 # You should have received a copy of the GNU General Public License 14 # along with this program; if not, write to the Free Software 15 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 17 import gobject 18 19 from sugar.graphics.xocolor import XoColor 20 from sugar.presence import presenceservice 21 from sugar import activity 22 23 from model.BuddyModel import BuddyModel 24 25 class ActivityModel: 26 def __init__(self, act, bundle): 27 self.activity = act 28 self.bundle = bundle 29 30 def get_id(self): 31 return self.activity.props.id 32 33 def get_icon_name(self): 34 return self.bundle.icon 35 36 def get_color(self): 37 return XoColor(self.activity.props.color) 38 39 def get_bundle_id(self): 40 return self.bundle.bundle_id 41 42 class Neighborhood(gobject.GObject): 43 __gsignals__ = { 44 'activity-added': (gobject.SIGNAL_RUN_FIRST, 45 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), 46 'activity-removed': (gobject.SIGNAL_RUN_FIRST, 47 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), 48 'buddy-added': (gobject.SIGNAL_RUN_FIRST, 49 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), 50 'buddy-moved': (gobject.SIGNAL_RUN_FIRST, 51 gobject.TYPE_NONE, 52 ([gobject.TYPE_PYOBJECT, 53 gobject.TYPE_PYOBJECT])), 54 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, 55 gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])) 56 } 57 58 def __init__(self): 59 gobject.GObject.__init__(self) 60 61 self._activities = {} 62 self._buddies = {} 63 64 self._pservice = presenceservice.get_instance() 65 self._pservice.connect("activity-appeared", 66 self._activity_appeared_cb) 67 self._pservice.connect('activity-disappeared', 68 self._activity_disappeared_cb) 69 self._pservice.connect("buddy-appeared", 70 self._buddy_appeared_cb) 71 self._pservice.connect("buddy-disappeared", 72 self._buddy_disappeared_cb) 73 74 # Add any buddies the PS knows about already 75 self._pservice.get_buddies_async(reply_handler=self._get_buddies_cb) 76 77 self._pservice.get_activities_async( 78 reply_handler=self._get_activities_cb) 79 80 def _get_buddies_cb(self, buddy_list): 81 for buddy in buddy_list: 82 self._buddy_appeared_cb(self._pservice, buddy) 83 84 def _get_activities_cb(self, activity_list): 85 for act in activity_list: 86 self._check_activity(act) 87 88 def get_activities(self): 89 return self._activities.values() 90 91 def get_buddies(self): 92 return self._buddies.values() 93 94 def _buddy_activity_changed_cb(self, model, cur_activity): 95 if not self._buddies.has_key(model.get_key()): 96 return 97 if cur_activity and self._activities.has_key(cur_activity.props.id): 98 activity_model = self._activities[cur_activity.props.id] 99 self.emit('buddy-moved', model, activity_model) 100 else: 101 self.emit('buddy-moved', model, None) 102 103 def _buddy_appeared_cb(self, pservice, buddy): 104 if self._buddies.has_key(buddy.props.key): 105 return 106 107 model = BuddyModel(buddy=buddy) 108 model.connect('current-activity-changed', 109 self._buddy_activity_changed_cb) 110 self._buddies[buddy.props.key] = model 111 self.emit('buddy-added', model) 112 113 cur_activity = buddy.props.current_activity 114 if cur_activity: 115 self._buddy_activity_changed_cb(model, cur_activity) 116 117 def _buddy_disappeared_cb(self, pservice, buddy): 118 if not self._buddies.has_key(buddy.props.key): 119 return 120 self.emit('buddy-removed', self._buddies[buddy.props.key]) 121 del self._buddies[buddy.props.key] 122 123 def _activity_appeared_cb(self, pservice, act): 124 self._check_activity(act) 125 126 def _check_activity(self, presence_activity): 127 registry = activity.get_registry() 128 bundle = registry.get_activity(presence_activity.props.type) 129 if not bundle: 130 return 131 if self.has_activity(presence_activity.props.id): 132 return 133 self.add_activity(bundle, presence_activity) 134 135 def has_activity(self, activity_id): 136 return self._activities.has_key(activity_id) 137 138 def get_activity(self, activity_id): 139 if self.has_activity(activity_id): 140 return self._activities[activity_id] 141 else: 142 return None 143 144 def add_activity(self, bundle, act): 145 model = ActivityModel(act, bundle) 146 self._activities[model.get_id()] = model 147 self.emit('activity-added', model) 148 149 for buddy in self._pservice.get_buddies(): 150 cur_activity = buddy.props.current_activity 151 key = buddy.props.key 152 if cur_activity == activity and self._buddies.has_key(key): 153 buddy_model = self._buddies[key] 154 self.emit('buddy-moved', buddy_model, model) 155 156 def _activity_disappeared_cb(self, pservice, act): 157 if self._activities.has_key(act.props.id): 158 activity_model = self._activities[act.props.id] 159 self.emit('activity-removed', activity_model) 160 del self._activities[act.props.id] 161 162 _model = None 163 164 def get_model(): 165 global _model 166 if _model is None: 167 _model = Neighborhood() 168 return _model -
new file src/model/network.py
diff --git a/src/model/network.py b/src/model/network.py new file mode 100644 index 0000000..d793deb
- + 1 # Copyright (C) 2008 Red Hat, Inc. 2 # 3 # This program is free software; you can redistribute it and/or modify 4 # it under the terms of the GNU General Public License as published by 5 # the Free Software Foundation; either version 2 of the License, or 6 # (at your option) any later version. 7 # 8 # This program is distributed in the hope that it will be useful, 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # GNU General Public License for more details. 12 # 13 # You should have received a copy of the GNU General Public License 14 # along with this program; if not, write to the Free Software 15 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 17 import logging 18 import os 19 20 import dbus 21 import ConfigParser 22 23 from sugar import dispatch 24 from sugar import env 25 26 DEVICE_TYPE_802_11_WIRELESS = 2 27 28 DEVICE_STATE_UNKNOWN = 0 29 DEVICE_STATE_UNMANAGED = 1 30 DEVICE_STATE_UNAVAILABLE = 2 31 DEVICE_STATE_DISCONNECTED = 3 32 DEVICE_STATE_PREPARE = 4 33 DEVICE_STATE_CONFIG = 5 34 DEVICE_STATE_NEED_AUTH = 6 35 DEVICE_STATE_IP_CONFIG = 7 36 DEVICE_STATE_ACTIVATED = 8 37 DEVICE_STATE_FAILED = 9 38 39 NM_802_11_AP_FLAGS_NONE = 0x00000000 40 NM_802_11_AP_FLAGS_PRIVACY = 0x00000001 41 42 NM_802_11_AP_SEC_NONE = 0x00000000 43 NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001 44 NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002 45 NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004 46 NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008 47 NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010 48 NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020 49 NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040 50 NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080 51 NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100 52 NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200 53 54 NM_802_11_MODE_UNKNOWN = 0 55 NM_802_11_MODE_ADHOC = 1 56 NM_802_11_MODE_INFRA = 2 57 58 NM_802_11_DEVICE_CAP_NONE = 0x00000000 59 NM_802_11_DEVICE_CAP_CIPHER_WEP40 = 0x00000001 60 NM_802_11_DEVICE_CAP_CIPHER_WEP104 = 0x00000002 61 NM_802_11_DEVICE_CAP_CIPHER_TKIP = 0x00000004 62 NM_802_11_DEVICE_CAP_CIPHER_CCMP = 0x00000008 63 NM_802_11_DEVICE_CAP_WPA = 0x00000010 64 NM_802_11_DEVICE_CAP_RSN = 0x00000020 65 66 SETTINGS_SERVICE = 'org.freedesktop.NetworkManagerUserSettings' 67 68 NM_SETTINGS_PATH = '/org/freedesktop/NetworkManagerSettings' 69 NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManagerSettings' 70 NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection' 71 NM_SECRETS_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection.Secrets' 72 73 _nm_settings = None 74 _conn_counter = 0 75 76 class WirelessSecurity(object): 77 def __init__(self): 78 self.key_mgmt = None 79 self.proto = None 80 self.group = None 81 self.pairwise = None 82 83 def get_dict(self): 84 wireless_security = {} 85 86 if self.key_mgmt is not None: 87 wireless_security['key-mgmt'] = self.key_mgmt 88 if self.proto is not None: 89 wireless_security['proto'] = self.proto 90 if self.pairwise is not None: 91 wireless_security['pairwise'] = self.pairwise 92 if self.group is not None: 93 wireless_security['group'] = self.group 94 95 return wireless_security 96 97 class Wireless(object): 98 def __init__(self): 99 self.ssid = None 100 101 def get_dict(self): 102 return {'ssid': self.ssid} 103 104 class Connection(object): 105 def __init__(self): 106 self.id = None 107 self.uuid = None 108 self.type = None 109 110 def get_dict(self): 111 return {'id': self.id, 112 'uuid': self.uuid, 113 'type': self.type} 114 115 class Settings(object): 116 def __init__(self): 117 self.connection = Connection() 118 self.wireless = Wireless() 119 self.wireless_security = None 120 121 def get_dict(self): 122 settings = {} 123 settings['connection'] = self.connection.get_dict() 124 settings['802-11-wireless'] = self.wireless.get_dict() 125 if self.wireless_security is not None: 126 settings['802-11-wireless-security'] = \ 127 self.wireless_security.get_dict() 128 return settings 129 130 class Secrets(object): 131 def __init__(self): 132 self.wep_key = None 133 self.psk = None 134 self.auth_alg = None 135 136 def get_dict(self): 137 secrets = {} 138 139 if self.wep_key is not None: 140 secrets['wep-key0'] = self.wep_key 141 if self.psk is not None: 142 secrets['psk'] = self.psk 143 if self.auth_alg is not None: 144 secrets['auth-alg'] = self.auth_alg 145 146 return {'802-11-wireless-security': secrets} 147 148 class NMSettings(dbus.service.Object): 149 def __init__(self): 150 bus = dbus.SystemBus() 151 bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus) 152 dbus.service.Object.__init__(self, bus_name, NM_SETTINGS_PATH) 153 154 self.connections = {} 155 self.secrets_request = dispatch.Signal() 156 157 @dbus.service.method(dbus_interface=NM_SETTINGS_IFACE, 158 in_signature='', out_signature='ao') 159 def ListConnections(self): 160 return self.connections.values() 161 162 @dbus.service.signal(NM_SETTINGS_IFACE, signature='o') 163 def NewConnection(self, connection_path): 164 pass 165 166 def add_connection(self, ssid, conn): 167 self.connections[ssid] = conn 168 conn.secrets_request.connect(self.__secrets_request_cb) 169 self.NewConnection(conn.path) 170 171 def __secrets_request_cb(self, sender, **kwargs): 172 self.secrets_request.send(self, connection=sender, 173 response=kwargs['response']) 174 175 class SecretsResponse(object): 176 ''' Intermediate object to report the secrets from the dialog 177 back to the connection object and which will inform NM 178 ''' 179 def __init__(self, connection, reply_cb, error_cb): 180 self._connection = connection 181 self._reply_cb = reply_cb 182 self._error_cb = error_cb 183 184 def set_secrets(self, secrets): 185 self._connection.set_secrets(secrets) 186 self._reply_cb(secrets.get_dict()) 187 188 def set_error(self, error): 189 self._error_cb(error) 190 191 class NMSettingsConnection(dbus.service.Object): 192 def __init__(self, path, settings, secrets): 193 bus = dbus.SystemBus() 194 bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus) 195 dbus.service.Object.__init__(self, bus_name, path) 196 197 self.path = path 198 self.secrets_request = dispatch.Signal() 199 200 self._settings = settings 201 self._secrets = secrets 202 203 def set_secrets(self, secrets): 204 self._secrets = secrets 205 self.save() 206 207 def save(self): 208 profile_path = env.get_profile_path() 209 config_path = os.path.join(profile_path, 'nm', 'connections.cfg') 210 211 config = ConfigParser.ConfigParser() 212 try: 213 try: 214 if not config.read(config_path): 215 logging.error('Error reading the nm config file') 216 return 217 except ConfigParser.ParsingError, e: 218 logging.error('Error reading the nm config file: %s' % e) 219 return 220 identifier = self._settings.connection.id 221 222 if identifier not in config.sections(): 223 config.add_section(identifier) 224 config.set(identifier, 'type', self._settings.connection.type) 225 config.set(identifier, 'ssid', self._settings.wireless.ssid) 226 config.set(identifier, 'uuid', self._settings.connection.uuid) 227 228 if self._settings.wireless_security is not None: 229 if self._settings.wireless_security.key_mgmt is not None: 230 config.set(identifier, 'key-mgmt', 231 self._settings.wireless_security.key_mgmt) 232 if self._settings.wireless_security.proto is not None: 233 config.set(identifier, 'proto', 234 self._settings.wireless_security.proto) 235 if self._settings.wireless_security.pairwise is not None: 236 config.set(identifier, 'pairwise', 237 self._settings.wireless_security.pairwise) 238 if self._settings.wireless_security.group is not None: 239 config.set(identifier, 'group', 240 self._settings.wireless_security.group) 241 if self._secrets is not None: 242 if self._settings.wireless_security.key_mgmt == 'none': 243 config.set(identifier, 'key', self._secrets.wep_key) 244 config.set(identifier, 'auth-alg', self._secrets.auth_alg) 245 elif self._settings.wireless_security.key_mgmt == 'wpa-psk': 246 config.set(identifier, 'key', self._secrets.psk) 247 except ConfigParser.Error, e: 248 logging.error('Error constructing %s: %s' % (identifier, e)) 249 else: 250 f = open(config_path, 'w') 251 try: 252 config.write(f) 253 except ConfigParser.Error, e: 254 logging.error('Can not write %s error: %s' % (config_path, e)) 255 f.close() 256 257 @dbus.service.method(dbus_interface=NM_CONNECTION_IFACE, 258 in_signature='', out_signature='a{sa{sv}}') 259 def GetSettings(self): 260 return self._settings.get_dict() 261 262 @dbus.service.method(dbus_interface=NM_SECRETS_IFACE, 263 async_callbacks=('reply', 'error'), 264 in_signature='sasb', out_signature='a{sa{sv}}') 265 def GetSecrets(self, setting_name, hints, request_new, reply, error): 266 logging.debug('Secrets requested for connection %s request_new=%s' 267 % (self.path, request_new)) 268 269 if request_new or self._secrets is None: 270 # request_new is for example the case when the pw on the AP changes 271 response = SecretsResponse(self, reply, error) 272 try: 273 self.secrets_request.send(self, response=response) 274 except Exception, e: 275 logging.error('Error requesting the secrets via dialog: %s' % e) 276 else: 277 reply(self._secrets.get_dict()) 278 279 def get_settings(): 280 global _nm_settings 281 if _nm_settings is None: 282 try: 283 _nm_settings = NMSettings() 284 except dbus.DBusException, e: 285 logging.error('Cannot create the UserSettings service %s.', e) 286 load_connections() 287 return _nm_settings 288 289 def find_connection(ssid): 290 connections = get_settings().connections 291 if ssid in connections: 292 return connections[ssid] 293 else: 294 return None 295 296 def add_connection(ssid, settings, secrets=None): 297 global _conn_counter 298 299 path = NM_SETTINGS_PATH + '/' + str(_conn_counter) 300 _conn_counter += 1 301 302 conn = NMSettingsConnection(path, settings, secrets) 303 _nm_settings.add_connection(ssid, conn) 304 return conn 305 306 def load_connections(): 307 profile_path = env.get_profile_path() 308 config_path = os.path.join(profile_path, 'nm', 'connections.cfg') 309 310 config = ConfigParser.ConfigParser() 311 312 if not os.path.exists(config_path): 313 if not os.path.exists(os.path.dirname(config_path)): 314 os.makedirs(os.path.dirname(config_path), 0755) 315 f = open(config_path, 'w') 316 config.write(f) 317 f.close() 318 319 try: 320 if not config.read(config_path): 321 logging.error('Error reading the nm config file') 322 return 323 except ConfigParser.ParsingError, e: 324 logging.error('Error reading the nm config file: %s' % e) 325 return 326 327 for section in config.sections(): 328 try: 329 settings = Settings() 330 settings.connection.id = section 331 ssid = config.get(section, 'ssid') 332 settings.wireless.ssid = dbus.ByteArray(ssid) 333 uuid = config.get(section, 'uuid') 334 settings.connection.uuid = uuid 335 nmtype = config.get(section, 'type') 336 settings.connection.type = nmtype 337 338 secrets = None 339 if config.has_option(section, 'key-mgmt'): 340 secrets = Secrets() 341 settings.wireless_security = WirelessSecurity() 342 mgmt = config.get(section, 'key-mgmt') 343 settings.wireless_security.key_mgmt = mgmt 344 key = config.get(section, 'key') 345 if mgmt == 'none': 346 secrets.wep_key = key 347 auth_alg = config.get(section, 'auth-alg') 348 secrets.auth_alg = auth_alg 349 elif mgmt == 'wpa-psk': 350 secrets.psk = key 351 if config.has_option(section, 'proto'): 352 value = config.get(section, 'proto') 353 settings.wireless_security.proto = value 354 if config.has_option(section, 'group'): 355 value = config.get(section, 'group') 356 settings.wireless_security.group = value 357 if config.has_option(section, 'pairwise'): 358 value = config.get(section, 'pairwise') 359 settings.wireless_security.pairwise = value 360 except ConfigParser.Error, e: 361 logging.error('Error reading section: %s' % e) 362 else: 363 add_connection(ssid, settings, secrets) -
src/model/shellmodel.py
diff --git a/src/model/shellmodel.py b/src/model/shellmodel.py index d1d8db8..7e786be 100644
a b import gobject 19 19 20 20 from sugar.presence import presenceservice 21 21 from model.Friends import Friends 22 from model.MeshModel import MeshModel23 22 from model.homemodel import HomeModel 24 23 from model.Owner import ShellOwner 25 24 from model.devices.devicesmodel import DevicesModel … … class ShellModel(gobject.GObject): 48 47 self._owner = ShellOwner() 49 48 50 49 self._friends = Friends() 51 self._mesh = MeshModel()52 50 self._home = HomeModel() 53 51 self._devices = DevicesModel() 54 52 … … class ShellModel(gobject.GObject): 70 68 if pspec.name == 'zoom-level': 71 69 return self.get_zoom_level() 72 70 73 def get_mesh(self):74 return self._mesh75 76 71 def get_friends(self): 77 72 return self._friends 78 73 -
src/view/devices/network/wireless.py
diff --git a/src/view/devices/network/wireless.py b/src/view/devices/network/wireless.py index 5bef0bb..a9cf22b 100644
a b 16 16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 17 18 18 from gettext import gettext as _ 19 import logging 20 import sha 19 21 20 22 import gtk 23 import dbus 21 24 22 25 from sugar.graphics.icon import get_icon_state 23 26 from sugar.graphics import style 24 27 from sugar.graphics.palette import Palette 25 28 from sugar.graphics.toolbutton import ToolButton 26 from sugar.graphics .xocolor import XoColor29 from sugar.graphics import xocolor 27 30 28 from model.devices.network import wireless 29 from model.devices import device 30 from hardware import hardwaremanager 31 from hardware import nmclient 31 from model import network 32 32 from view.frame.frameinvoker import FrameWidgetInvoker 33 33 from view.pulsingicon import PulsingIcon 34 34 … … _ICON_NAME = 'network-wireless' 36 36 37 37 IP_ADDRESS_TEXT_TEMPLATE = _("IP address: %s") 38 38 39 class DeviceView(ToolButton): 40 41 FRAME_POSITION_RELATIVE = 300 42 43 def __init__(self, model): 44 ToolButton.__init__(self) 45 self._model = model 46 47 self._icon = PulsingIcon() 48 self._icon.props.icon_name = _ICON_NAME 49 pulse_color = XoColor("%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), 50 style.COLOR_TRANSPARENT.get_svg())) 51 self._icon.props.pulse_color = pulse_color 52 self._icon.props.base_color = pulse_color # only temporarily 53 self._inactive_color = XoColor("%s,%s" % ( 54 style.COLOR_INACTIVE_STROKE.get_html(), 55 style.COLOR_INACTIVE_FILL.get_html())) 56 57 meshdev = None 58 network_manager = hardwaremanager.get_network_manager() 59 for dev in network_manager.get_devices(): 60 if dev.get_type() == nmclient.DEVICE_TYPE_802_11_MESH_OLPC: 61 meshdev = dev 62 break 63 64 self._counter = 0 65 self.palette = WirelessPalette(self._get_palette_primary_text(), 66 meshdev) 67 self.set_palette(self.palette) 68 self.palette.props.invoker = FrameWidgetInvoker(self) 69 self.palette.set_group_id('frame') 70 self.palette.set_frequency(self._model.props.frequency) 71 72 model.connect('notify::name', self._name_changed_cb) 73 model.connect('notify::ip-address', self._ip_address_changed_cb) 74 model.connect('notify::strength', self._strength_changed_cb) 75 model.connect('notify::state', self._state_changed_cb) 76 77 self._update_icon() 78 self._update_state() 79 self._update_ip_address() 80 81 self.set_icon_widget(self._icon) 82 self._icon.show() 83 84 def _get_palette_primary_text(self): 85 if self._model.props.state == device.STATE_INACTIVE: 86 return _("Disconnected") 87 return self._model.props.name 88 89 def _strength_changed_cb(self, model, pspec): 90 self._update_icon() 91 # Only update frequency periodically 92 if self._counter % 4 == 0: 93 self.palette.set_frequency(self._model.props.frequency) 94 self._counter += 1 95 96 def _ip_address_changed_cb(self, model, pspec): 97 self._update_ip_address() 98 99 def _name_changed_cb(self, model, pspec): 100 self.palette.set_primary_text(self._get_palette_primary_text()) 101 self._update_state() 102 103 def _state_changed_cb(self, model, pspec): 104 self._update_icon() 105 self._update_state() 106 self.palette.set_primary_text(self._get_palette_primary_text()) 107 108 def _update_icon(self): 109 # keep this code in sync with view/home/MeshBox.py 110 strength = self._model.props.strength 111 if self._model.props.state == device.STATE_INACTIVE: 112 strength = 0 113 if self._model.props.state == device.STATE_ACTIVATED: 114 icon_name = '%s-connected' % _ICON_NAME 115 else: 116 icon_name = _ICON_NAME 117 icon_name = get_icon_state(icon_name, strength) 118 if icon_name: 119 self._icon.props.icon_name = icon_name 120 121 def _update_state(self): 122 # FIXME Change icon colors once we have real icons 123 state = self._model.props.state 124 self._icon.props.pulsing = state == device.STATE_ACTIVATING 125 if state == device.STATE_ACTIVATING: 126 fill = style.COLOR_INACTIVE_FILL.get_svg() 127 stroke = style.COLOR_INACTIVE_STROKE.get_svg() 128 elif state == device.STATE_ACTIVATED: 129 (stroke, fill) = self._model.get_active_network_colors() 130 elif state == device.STATE_INACTIVE: 131 fill = style.COLOR_INACTIVE_FILL.get_svg() 132 stroke = style.COLOR_INACTIVE_STROKE.get_svg() 133 self._icon.props.base_color = XoColor("%s,%s" % (stroke, fill)) 134 135 def _update_ip_address(self): 136 self.palette.set_ip_address(self._model.props.ip_address) 39 _NM_SERVICE = 'org.freedesktop.NetworkManager' 40 _NM_IFACE = 'org.freedesktop.NetworkManager' 41 _NM_PATH = '/org/freedesktop/NetworkManager' 42 _NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' 43 _NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' 44 _NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' 45 _NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' 46 47 _NM_DEVICE_STATE_UNKNOWN = 0 48 _NM_DEVICE_STATE_UNMANAGED = 1 49 _NM_DEVICE_STATE_UNAVAILABLE = 2 50 _NM_DEVICE_STATE_DISCONNECTED = 3 51 _NM_DEVICE_STATE_PREPARE = 4 52 _NM_DEVICE_STATE_CONFIG = 5 53 _NM_DEVICE_STATE_NEED_AUTH = 6 54 _NM_DEVICE_STATE_IP_CONFIG = 7 55 _NM_DEVICE_STATE_ACTIVATED = 8 56 _NM_DEVICE_STATE_FAILED = 9 57 58 def freq_to_channel(freq): 59 ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4, 60 2432: 5, 2437: 6, 2442: 7, 2447: 8, 61 2452: 9, 2457: 10, 2462: 11, 2467: 12, 62 2472: 13} 63 return ftoc[freq] 137 64 138 65 class WirelessPalette(Palette): 139 def __init__(self, primary_text, meshdev): 140 Palette.__init__(self, primary_text, menu_after_content=True) 141 self._meshdev = meshdev 66 def __init__(self, primary_text, device_view): 67 Palette.__init__(self, label=primary_text) 68 69 self._device_view = device_view 70 self._disconnect_item = None 142 71 143 72 self._chan_label = gtk.Label() 144 73 self._chan_label.props.xalign = 0.0 … … class WirelessPalette(Palette): 146 75 147 76 self._ip_address_label = gtk.Label() 148 77 149 vbox= gtk.VBox()78 self._info = gtk.VBox() 150 79 151 80 def _padded(child, xalign=0, yalign=0.5): 152 81 padder = gtk.Alignment(xalign=xalign, yalign=yalign, … … class WirelessPalette(Palette): 158 87 padder.add(child) 159 88 return padder 160 89 161 vbox.pack_start(_padded(self._chan_label)) 162 vbox.pack_start(_padded(self._ip_address_label)) 163 vbox.show_all() 90 self._info.pack_start(_padded(self._chan_label)) 91 self._info.pack_start(_padded(self._ip_address_label)) 92 self._info.show_all() 93 94 self._disconnect_item = gtk.MenuItem(_('Disconnect...')) 95 self._disconnect_item.connect('activate', self._disconnect_activate_cb) 96 self.menu.append(self._disconnect_item) 97 98 self.disconnected() 164 99 165 if meshdev: 166 disconnect_item = gtk.MenuItem(_('Disconnect...')) 167 disconnect_item.connect('activate', self._disconnect_activate_cb) 168 self.menu.append(disconnect_item) 169 disconnect_item.show() 100 def connecting(self): 101 self.props.secondary_text = _('Connecting...') 170 102 171 self.set_content(vbox) 103 def connected(self, frequency, iaddress): 104 self.set_content(self._info) 105 self.props.secondary_text = _('Connected') 106 self._set_channel(frequency) 107 self._set_ip_address(iaddress) 108 self._disconnect_item.show() 109 110 def disconnected(self): 111 self.props.primary_text = '' 112 self.props.secondary_text = _('Not connected') 113 self.set_content(None) 114 self._disconnect_item.hide() 172 115 173 116 def _disconnect_activate_cb(self, menuitem): 174 # Disconnection for an AP means activating the default mesh device 175 network_manager = hardwaremanager.get_network_manager() 176 if network_manager and self._meshdev: 177 network_manager.set_active_device(self._meshdev) 117 self._device_view.deactivate_connection() 118 119 def _inet_ntoa(self, iaddress): 120 address = ['%s' % ((iaddress >> i) % 256) for i in [0, 8, 16, 24]] 121 return ".".join(address) 178 122 179 def set_frequency(self, freq):123 def _set_channel(self, freq): 180 124 try: 181 chan = wireless.freq_to_channel(freq)125 chan = freq_to_channel(freq) 182 126 except KeyError: 183 127 chan = 0 184 128 self._chan_label.set_text("%s: %d" % (_("Channel"), chan)) 185 129 186 def set_ip_address(self, ip_address): 187 if ip_address is not None and ip_address != "0.0.0.0": 188 ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % ip_address 130 def _set_ip_address(self, ip_address): 131 if ip_address is not None: 132 ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % \ 133 self._inet_ntoa(ip_address) 189 134 else: 190 135 ip_address_text = "" 191 136 self._ip_address_label.set_text(ip_address_text) 137 138 139 class DeviceView(ToolButton): 140 141 FRAME_POSITION_RELATIVE = 300 142 143 def __init__(self, device): 144 ToolButton.__init__(self) 145 146 self._bus = dbus.SystemBus() 147 self._device = device.nm_device 148 self._flags = 0 149 self._name = '' 150 self._strength = 0 151 self._frequency = 0 152 self._device_state = None 153 self._color = None 154 self._active_ap_op = None 155 156 self._icon = PulsingIcon() 157 self._icon.props.icon_name = get_icon_state(_ICON_NAME, 0) 158 self._inactive_color = xocolor.XoColor( \ 159 "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), 160 style.COLOR_TRANSPARENT.get_svg())) 161 self._icon.props.pulse_color = self._inactive_color 162 self._icon.props.base_color = self._inactive_color 163 164 self.set_icon_widget(self._icon) 165 self._icon.show() 166 167 self._palette = WirelessPalette(self._name, self) 168 self.set_palette(self._palette) 169 self._palette.props.invoker = FrameWidgetInvoker(self) 170 self._palette.set_group_id('frame') 171 172 self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', 173 reply_handler=self.__get_active_ap_reply_cb, 174 error_handler=self.__get_active_ap_error_cb) 175 176 self._bus.add_signal_receiver(self.__state_changed_cb, 177 signal_name='StateChanged', 178 path=self._device.object_path, 179 dbus_interface=_NM_DEVICE_IFACE) 180 181 def disconnect(self): 182 self._bus.remove_signal_receiver(self.__state_changed_cb, 183 signal_name='StateChanged', 184 path=self._device.object_path, 185 dbus_interface=_NM_DEVICE_IFACE) 186 187 def __get_active_ap_reply_cb(self, active_ap_op): 188 if self._active_ap_op != active_ap_op: 189 if self._active_ap_op is not None: 190 self._bus.remove_signal_receiver( 191 self.__ap_properties_changed_cb, 192 signal_name='PropertiesChanged', 193 path=self._active_ap_op, 194 dbus_interface=_NM_ACCESSPOINT_IFACE) 195 if active_ap_op == '/': 196 self._active_ap_op = None 197 return 198 self._active_ap_op = active_ap_op 199 active_ap = self._bus.get_object(_NM_SERVICE, active_ap_op) 200 props = dbus.Interface(active_ap, 'org.freedesktop.DBus.Properties') 201 202 props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, 203 reply_handler=self.__get_all_props_reply_cb, 204 error_handler=self.__get_all_props_error_cb) 205 206 self._bus.add_signal_receiver(self.__ap_properties_changed_cb, 207 signal_name='PropertiesChanged', 208 path=self._active_ap_op, 209 dbus_interface=_NM_ACCESSPOINT_IFACE) 210 211 def __get_active_ap_error_cb(self, err): 212 logging.debug('Error getting the active access point: %s', err) 213 214 def __state_changed_cb(self, new_state, old_state, reason): 215 self._device_state = new_state 216 self._update_state() 217 218 self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', 219 reply_handler=self.__get_active_ap_reply_cb, 220 error_handler=self.__get_active_ap_error_cb) 221 222 def __ap_properties_changed_cb(self, properties): 223 self._update_properties(properties) 224 225 def _update_properties(self, properties): 226 if 'Ssid' in properties: 227 self._name = properties['Ssid'] 228 if 'Strength' in properties: 229 self._strength = properties['Strength'] 230 if 'Flags' in properties: 231 self._flags = properties['Flags'] 232 if 'Frequency' in properties: 233 self._frequency = properties['Frequency'] 234 235 sh = sha.new() 236 data = self._name + hex(self._flags) 237 sh.update(data) 238 h = hash(sh.digest()) 239 idx = h % len(xocolor.colors) 240 241 self._color = xocolor.XoColor('%s,%s' % (xocolor.colors[idx][0], 242 xocolor.colors[idx][1])) 243 self._update() 244 245 def __get_all_props_reply_cb(self, properties): 246 self._update_properties(properties) 247 248 def __get_all_props_error_cb(self, err): 249 logging.debug('Error getting the access point properties: %s', err) 250 251 def _update(self): 252 if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: 253 self._icon.props.badge_name = "emblem-locked" 254 else: 255 self._icon.props.badge_name = None 256 257 self._palette.props.primary_text = self._name 258 259 self._update_state() 260 self._update_color() 261 262 def _update_state(self): 263 if self._active_ap_op is not None: 264 state = self._device_state 265 else: 266 state = network.DEVICE_STATE_UNKNOWN 267 268 if state == network.DEVICE_STATE_ACTIVATED: 269 icon_name = '%s-connected' % _ICON_NAME 270 else: 271 icon_name = _ICON_NAME 272 273 icon_name = get_icon_state(icon_name, self._strength) 274 if icon_name: 275 self._icon.props.icon_name = icon_name 276 277 if state == network.DEVICE_STATE_PREPARE or \ 278 state == network.DEVICE_STATE_CONFIG or \ 279 state == network.DEVICE_STATE_NEED_AUTH or \ 280 state == network.DEVICE_STATE_IP_CONFIG: 281 self._palette.connecting() 282 self._icon.props.pulsing = True 283 elif state == network.DEVICE_STATE_ACTIVATED: 284 props = dbus.Interface(self._device, 285 'org.freedesktop.DBus.Properties') 286 address = props.Get(_NM_DEVICE_IFACE, 'Ip4Address') 287 self._palette.connected(self._frequency, address) 288 self._icon.props.pulsing = False 289 else: 290 self._palette.disconnected() 291 self._icon.props.pulsing = False 292 self._icon.props.base_color = self._inactive_color 293 self._icon.props.badge_name = None 294 self._name = '' 295 296 def _update_color(self): 297 self._icon.props.base_color = self._color 298 299 def deactivate_connection(self): 300 if self._active_ap_op is not None: 301 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) 302 netmgr = dbus.Interface(obj, _NM_IFACE) 303 netmgr_props = dbus.Interface( 304 netmgr, 'org.freedesktop.DBus.Properties') 305 active_connections_o = netmgr_props.Get(_NM_IFACE, 306 'ActiveConnections') 307 308 for conn_o in active_connections_o: 309 obj = self._bus.get_object(_NM_IFACE, conn_o) 310 props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') 311 ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') 312 if ap_op == self._active_ap_op: 313 netmgr.DeactivateConnection(conn_o) 314 break -
src/view/home/Makefile.am
diff --git a/src/view/home/Makefile.am b/src/view/home/Makefile.am index b323589..9e4a754 100644
a b sugar_PYTHON = \ 7 7 grid.py \ 8 8 FriendView.py \ 9 9 FriendsBox.py \ 10 keydialog.py \ 10 11 HomeBox.py \ 11 12 HomeWindow.py \ 12 13 MeshBox.py \ -
src/view/home/MeshBox.py
diff --git a/src/view/home/MeshBox.py b/src/view/home/MeshBox.py index 8cf8af6..568e1b9 100644
a b 16 16 17 17 from gettext import gettext as _ 18 18 import logging 19 import sha 19 20 21 import dbus 20 22 import hippo 21 23 import gobject 22 24 import gtk 23 25 24 26 from sugar.graphics.icon import CanvasIcon, Icon 25 27 from sugar.graphics.xocolor import XoColor 28 from sugar.graphics import xocolor 26 29 from sugar.graphics import style 27 30 from sugar.graphics.icon import get_icon_state 28 31 from sugar.graphics import palette 29 32 from sugar.graphics import iconentry 30 33 from sugar.graphics.menuitem import MenuItem 31 from sugar import profile34 from sugar.util import unique_id 32 35 33 from model import accesspointmodel 34 from model.devices.network import wireless 35 from model import shellmodel 36 from hardware import hardwaremanager 37 from hardware import nmclient 36 from model import neighborhood 38 37 from view.BuddyIcon import BuddyIcon 39 38 from view.pulsingicon import CanvasPulsingIcon 40 39 from view.home.snowflakelayout import SnowflakeLayout 41 40 from view.home.spreadlayout import SpreadLayout 41 from view.home import keydialog 42 from model import network 43 from model.network import Settings 44 from model.network import WirelessSecurity 42 45 import view.Shell 43 46 44 from hardware.nmclient import NM_802_11_CAP_PROTO_WEP, \ 45 NM_802_11_CAP_PROTO_WPA, NM_802_11_CAP_PROTO_WPA2 46 47 _NM_SERVICE = 'org.freedesktop.NetworkManager' 48 _NM_IFACE = 'org.freedesktop.NetworkManager' 49 _NM_PATH = '/org/freedesktop/NetworkManager' 50 _NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' 51 _NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' 52 _NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' 53 _NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' 47 54 48 55 _ICON_NAME = 'network-wireless' 49 56 50 57 class AccessPointView(CanvasPulsingIcon): 51 def __init__(self, model, mesh_device=None):58 def __init__(self, device, model): 52 59 CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE, 53 60 cache=True) 61 self._bus = dbus.SystemBus() 62 self._device = device 54 63 self._model = model 55 self._ meshdev = mesh_device64 self._palette_icon = None 56 65 self._disconnect_item = None 57 66 self._connect_item = None 58 67 self._greyed_out = False 68 self._name = '' 69 self._strength = 0 70 self._flags = 0 71 self._wpa_flags = 0 72 self._rsn_flags = 0 73 self._mode = 0 74 self._device_caps = 0 75 self._device_state = None 76 self._connection = None 77 self._active = True 78 self._color = None 59 79 60 80 self.connect('activated', self._activate_cb) 61 81 62 model.connect('notify::strength', self._strength_changed_cb)63 model.connect('notify::name', self._name_changed_cb)64 model.connect('notify::state', self._state_changed_cb)65 66 82 pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), 67 83 style.COLOR_TRANSPARENT.get_svg())) 68 84 self.props.pulse_color = pulse_color 69 85 70 # Update badge71 caps = model.props.capabilities72 if model.get_nm_network().is_favorite():73 self.props.badge_name = "emblem-favorite"74 elif (caps & NM_802_11_CAP_PROTO_WEP) or \75 (caps & NM_802_11_CAP_PROTO_WPA) or \76 (caps & NM_802_11_CAP_PROTO_WPA2):77 self.props.badge_name = "emblem-locked"78 79 86 self._palette = self._create_palette() 80 87 self.set_palette(self._palette) 81 88 82 self._update_icon() 83 self._update_name() 84 self._update_state() 89 model_props = dbus.Interface(model, 'org.freedesktop.DBus.Properties') 90 model_props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, 91 reply_handler=self.__get_all_props_reply_cb, 92 error_handler=self.__get_all_props_error_cb) 93 94 self._bus.add_signal_receiver(self.__ap_properties_changed_cb, 95 signal_name='PropertiesChanged', 96 path=model.object_path, 97 dbus_interface=_NM_ACCESSPOINT_IFACE) 98 99 self._device.Get(_NM_DEVICE_IFACE, 'State', 100 reply_handler=self.__get_device_state_reply_cb, 101 error_handler=self.__get_device_state_error_cb) 102 self._device.Get(_NM_WIRELESS_IFACE, 'WirelessCapabilities', 103 reply_handler=self.__get_device_caps_reply_cb, 104 error_handler=self.__get_device_caps_error_cb) 105 self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', 106 reply_handler=self.__get_active_ap_reply_cb, 107 error_handler=self.__get_active_ap_error_cb) 108 109 self._bus.add_signal_receiver(self.__device_state_changed_cb, 110 signal_name='StateChanged', 111 path=device.object_path, 112 dbus_interface=_NM_DEVICE_IFACE) 113 self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, 114 signal_name='PropertiesChanged', 115 path=device.object_path, 116 dbus_interface=_NM_WIRELESS_IFACE) 85 117 86 118 def _create_palette(self): 87 icon_name = get_icon_state(_ICON_NAME, self._model.props.strength) 88 palette_icon = Icon(icon_name=icon_name, 89 icon_size=style.STANDARD_ICON_SIZE, 90 badge_name=self.props.badge_name) 91 ap_color = self._model.get_nm_network().get_colors() 92 palette_icon.props.xo_color = XoColor('%s,%s' % ap_color) 119 icon_name = get_icon_state(_ICON_NAME, self._strength) 120 self._palette_icon = Icon(icon_name=icon_name, 121 icon_size=style.STANDARD_ICON_SIZE, 122 badge_name=self.props.badge_name) 93 123 94 p = palette.Palette(primary_text=self._ model.props.name,95 icon= palette_icon)124 p = palette.Palette(primary_text=self._name, 125 icon=self._palette_icon) 96 126 97 127 self._connect_item = MenuItem(_('Connect'), 'dialog-ok') 98 128 self._connect_item.connect('activate', self._activate_cb) 99 129 p.menu.append(self._connect_item) 100 130 101 # Only show disconnect when there's a mesh device, because mesh takes 102 # priority over the normal wireless device. NM doesn't have a 103 # "disconnect" method for a device either (for various reasons) 104 # so this doesn't have a good mapping 105 if self._meshdev: 106 self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject') 107 self._disconnect_item.connect('activate', 108 self._disconnect_activate_cb) 109 p.menu.append(self._disconnect_item) 131 self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject') 132 self._disconnect_item.connect('activate', 133 self._disconnect_activate_cb) 134 p.menu.append(self._disconnect_item) 110 135 111 136 return p 112 137 113 def _disconnect_activate_cb(self, menuitem): 114 # Disconnection for an AP means activating the default mesh device 115 network_manager = hardwaremanager.get_network_manager() 116 if network_manager and self._meshdev: 117 network_manager.set_active_device(self._meshdev) 118 self._palette.props.secondary_text = _('Disconnecting...') 119 self.props.pulsing = False 138 def __device_state_changed_cb(self, new_state, old_state, reason): 139 self._device_state = new_state 140 self._update_state() 141 142 def __ap_properties_changed_cb(self, properties): 143 self._update_properties(properties) 144 145 def __wireless_properties_changed_cb(self, properties): 146 if 'ActiveAccessPoint' in properties: 147 ap = properties['ActiveAccessPoint'] 148 self._active = (ap == self._model.object_path) 149 self._update_state() 150 151 def _update_properties(self, properties): 152 if 'Ssid' in properties: 153 self._name = properties['Ssid'] 154 if 'Strength' in properties: 155 self._strength = properties['Strength'] 156 if 'Flags' in properties: 157 self._flags = properties['Flags'] 158 if 'WpaFlags' in properties: 159 self._wpa_flags = properties['WpaFlags'] 160 if 'RsnFlags' in properties: 161 self._rsn_flags = properties['RsnFlags'] 162 if 'Mode' in properties: 163 self._mode = properties['Mode'] 164 165 sh = sha.new() 166 data = self._name + hex(self._flags) 167 sh.update(data) 168 h = hash(sh.digest()) 169 idx = h % len(xocolor.colors) 170 171 self._color = XoColor('%s,%s' % (xocolor.colors[idx][0], 172 xocolor.colors[idx][1])) 173 174 self._update() 175 176 def __get_active_ap_reply_cb(self, ap): 177 self._active = (ap == self._model.object_path) 178 self._update_state() 179 180 def __get_active_ap_error_cb(self, err): 181 logging.debug('Error getting the active access point: %s', err) 182 183 def __get_device_caps_reply_cb(self, caps): 184 self._device_caps = caps 120 185 121 def _ strength_changed_cb(self, model, pspec):122 self._update_icon()186 def __get_device_caps_error_cb(self, err): 187 logging.debug('Error getting the wireless device properties: %s', err) 123 188 124 def _name_changed_cb(self, model, pspec): 125 self._update_name() 189 def __get_device_state_reply_cb(self, state): 190 self._device_state = state 191 self._update() 192 193 def __get_device_state_error_cb(self, err): 194 logging.debug('Error getting the access point properties: %s', err) 195 196 def __get_all_props_reply_cb(self, properties): 197 self._update_properties(properties) 198 199 def __get_all_props_error_cb(self, err): 200 logging.debug('Error getting the access point properties: %s', err) 201 202 def _update(self): 203 if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: 204 self.props.badge_name = "emblem-locked" 205 self._palette_icon.props.badge_name = "emblem-locked" 206 else: 207 self.props.badge_name = None 208 self._palette_icon.props.badge_name = None 209 210 self._palette.props.primary_text = self._name 126 211 127 def _state_changed_cb(self, model, pspec):128 self._update_icon()129 212 self._update_state() 213 self._update_color() 130 214 131 def _activate_cb(self, icon): 132 network_manager = hardwaremanager.get_network_manager() 133 if network_manager: 134 device = self._model.get_nm_device() 135 network = self._model.get_nm_network() 136 network_manager.set_active_device(device, network) 137 138 def _update_name(self): 139 self._palette.props.primary_text = self._model.props.name 140 141 def _update_icon(self): 142 # keep this code in sync with view/devices/network/wireless.py 143 strength = self._model.props.strength 144 if self._model.props.state == accesspointmodel.STATE_CONNECTED: 215 def _update_state(self): 216 if self._active: 217 state = self._device_state 218 else: 219 state = network.DEVICE_STATE_UNKNOWN 220 221 if state == network.DEVICE_STATE_ACTIVATED: 145 222 icon_name = '%s-connected' % _ICON_NAME 146 223 else: 147 224 icon_name = _ICON_NAME 148 icon_name = get_icon_state(icon_name, strength) 225 226 icon_name = get_icon_state(icon_name, self._strength) 149 227 if icon_name: 150 228 self.props.icon_name = icon_name 151 229 icon = self._palette.props.icon 152 230 icon.props.icon_name = icon_name 153 231 154 def _update_state(self): 155 if self._model.props.state == accesspointmodel.STATE_CONNECTING: 232 if state == network.DEVICE_STATE_PREPARE or \ 233 state == network.DEVICE_STATE_CONFIG or \ 234 state == network.DEVICE_STATE_NEED_AUTH or \ 235 state == network.DEVICE_STATE_IP_CONFIG: 156 236 if self._disconnect_item: 157 237 self._disconnect_item.show() 158 238 self._connect_item.hide() 159 239 self._palette.props.secondary_text = _('Connecting...') 160 240 self.props.pulsing = True 161 elif s elf._model.props.state == accesspointmodel.STATE_CONNECTED:241 elif state == network.DEVICE_STATE_ACTIVATED: 162 242 if self._disconnect_item: 163 243 self._disconnect_item.show() 164 244 self._connect_item.hide() 165 # TODO: show the channel number166 245 self._palette.props.secondary_text = _('Connected') 167 246 self.props.pulsing = False 168 el if self._model.props.state == accesspointmodel.STATE_NOTCONNECTED:247 else: 169 248 if self._disconnect_item: 170 249 self._disconnect_item.hide() 171 250 self._connect_item.show() 172 # TODO: show the channel number173 251 self._palette.props.secondary_text = None 174 252 self.props.pulsing = False 175 253 254 def _update_color(self): 176 255 if self._greyed_out: 177 256 self.props.pulsing = False 178 257 self.props.base_color = XoColor('#D5D5D5,#D5D5D5') 179 258 else: 180 self.props.base_color = XoColor('%s,%s' % \ 181 self._model.get_nm_network().get_colors()) 182 183 def set_filter(self, query): 184 self._greyed_out = self._model.props.name.lower().find(query) == -1 185 self._update_state() 186 187 _MESH_ICON_NAME = 'network-mesh' 188 189 class MeshDeviceView(CanvasPulsingIcon): 190 def __init__(self, nm_device, channel): 191 if not channel in [1, 6, 11]: 192 raise ValueError("Invalid channel %d" % channel) 193 194 CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE, 195 icon_name=_MESH_ICON_NAME, cache=True) 196 197 self._nm_device = nm_device 198 self.channel = channel 199 self.props.badge_name = "badge-channel-%d" % self.channel 200 self._greyed_out = False 259 self.props.base_color = self._color 201 260 202 self._disconnect_item = None 203 self._palette = self._create_palette() 204 self.set_palette(self._palette) 261 self._palette_icon.props.xo_color = self._color 205 262 206 pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), 207 style.COLOR_TRANSPARENT.get_svg())) 208 self.props.pulse_color = pulse_color 263 def _disconnect_activate_cb(self, item): 264 pass 209 265 210 self.connect('activated', self._activate_cb)211 266 212 self._nm_device.connect('state-changed', self._state_changed_cb) 213 self._nm_device.connect('activation-stage-changed', 214 self._state_changed_cb) 215 self._update_state() 267 def _add_ciphers_from_flags(self, flags, pairwise): 268 ciphers = [] 269 if pairwise: 270 if flags & network.NM_802_11_AP_SEC_PAIR_TKIP: 271 ciphers.append("tkip") 272 if flags & network.NM_802_11_AP_SEC_PAIR_CCMP: 273 ciphers.append("ccmp") 274 else: 275 if flags & network.NM_802_11_AP_SEC_GROUP_WEP40: 276 ciphers.append("wep40") 277 if flags & network.NM_802_11_AP_SEC_GROUP_WEP104: 278 ciphers.append("wep104") 279 if flags & network.NM_802_11_AP_SEC_GROUP_TKIP: 280 ciphers.append("tkip") 281 if flags & network.NM_802_11_AP_SEC_GROUP_CCMP: 282 ciphers.append("ccmp") 283 return ciphers 284 285 def _get_security(self): 286 if not (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ 287 (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ 288 (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): 289 # No security 290 return None 291 292 if (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ 293 (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ 294 (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): 295 # Static WEP, Dynamic WEP, or LEAP 296 wireless_security = WirelessSecurity() 297 wireless_security.key_mgmt = 'none' 298 return wireless_security 299 300 if (self._mode != network.NM_802_11_MODE_INFRA): 301 # Stuff after this point requires infrastructure 302 logging.error('The infrastructure mode is not supoorted' 303 ' by your wireless device.') 304 return None 305 306 if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ 307 (self._device_caps & network.NM_802_11_DEVICE_CAP_RSN): 308 # WPA2 PSK first 309 pairwise = self._add_ciphers_from_flags(self._rsn_flags, True) 310 group = self._add_ciphers_from_flags(self._rsn_flags, False) 311 wireless_security = WirelessSecurity() 312 wireless_security.key_mgmt = 'wpa-psk' 313 wireless_security.proto = 'rsn' 314 wireless_security.pairwise = pairwise 315 wireless_security.group = group 316 return wireless_security 317 318 if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ 319 (self._device_caps & network.NM_802_11_DEVICE_CAP_WPA): 320 # WPA PSK 321 pairwise = self._add_ciphers_from_flags(self._wpa_flags, True) 322 group = self._add_ciphers_from_flags(self._wpa_flags, False) 323 wireless_security = WirelessSecurity() 324 wireless_security.key_mgmt = 'wpa-psk' 325 wireless_security.proto = 'wpa' 326 wireless_security.pairwise = pairwise 327 wireless_security.group = group 328 return wireless_security 216 329 217 def _create_palette(self): 218 p = palette.Palette(_("Mesh Network") + " " + str(self.channel), 219 menu_after_content=True) 330 def _activate_cb(self, icon): 331 connection = network.find_connection(self._name) 332 if connection is None: 333 settings = Settings() 334 settings.connection.id = 'Auto ' + self._name 335 settings.connection.uuid = unique_id() 336 settings.connection.type = '802-11-wireless' 337 settings.wireless.ssid = self._name 220 338 221 self._disconnect_item = gtk.MenuItem(_('Disconnect...')) 222 self._disconnect_item.connect('activate', self._disconnect_activate_cb) 223 p.menu.append(self._disconnect_item) 339 wireless_security = self._get_security() 340 settings.wireless_security = wireless_security 224 341 225 state = self._nm_device.get_state() 226 chan = wireless.freq_to_channel(self._nm_device.get_frequency()) 227 if state == nmclient.DEVICE_STATE_ACTIVATED and chan == self.channel: 228 self._disconnect_item.show() 229 return p 342 connection = network.add_connection(self._name, settings) 230 343 231 def _disconnect_activate_cb(self, menuitem): 232 network_manager = hardwaremanager.get_network_manager() 233 if network_manager: 234 network_manager.set_active_device(self._nm_device) 344 if wireless_security is None: 345 self._connection = connection 235 346 236 def _activate_cb(self, icon): 237 network_manager = hardwaremanager.get_network_manager() 238 if network_manager: 239 freq = wireless.channel_to_freq(self.channel) 240 network_manager.set_active_device(self._nm_device, mesh_freq=freq) 347 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) 348 netmgr = dbus.Interface(obj, _NM_IFACE) 241 349 242 def _state_changed_cb(self, model): 243 self._update_state() 350 netmgr.ActivateConnection(network.SETTINGS_SERVICE, connection.path, 351 self._device.object_path, 352 self._model.object_path, 353 reply_handler=self.__activate_reply_cb, 354 error_handler=self.__activate_error_cb) 244 355 245 def _update_state(self): 246 state = self._nm_device.get_state() 247 chan = wireless.freq_to_channel(self._nm_device.get_frequency()) 248 if state == nmclient.DEVICE_STATE_ACTIVATING and chan == self.channel: 249 self._disconnect_item.hide() 250 self.props.pulsing = True 251 elif state == nmclient.DEVICE_STATE_ACTIVATED and chan == self.channel: 252 self._disconnect_item.show() 253 self.props.pulsing = False 254 elif state == nmclient.DEVICE_STATE_INACTIVE or chan != self.channel: 255 self._disconnect_item.hide() 256 self.props.pulsing = False 356 def __activate_reply_cb(self, connection): 357 if self._connection: 358 self._connection.save() 359 logging.debug('Connection activated: %s', connection) 257 360 258 if self._greyed_out: 259 self.props.pulsing = False 260 self.props.base_color = XoColor('#D5D5D5,#D5D5D5') 261 else: 262 self.props.base_color = profile.get_color() 361 def __activate_error_cb(self, err): 362 logging.debug('Failed to activate connection: %s', err) 263 363 264 364 def set_filter(self, query): 265 self._greyed_out = (query != '')365 self._greyed_out = self._name.lower().find(query) == -1 266 366 self._update_state() 367 self._update_color() 368 369 def create_keydialog(self, response): 370 keydialog.create(self._name, self._flags, self._wpa_flags, 371 self._rsn_flags, self._device_caps, response) 372 373 def disconnect(self): 374 self._bus.remove_signal_receiver(self.__ap_properties_changed_cb, 375 signal_name='PropertiesChanged', 376 path=self._model.object_path, 377 dbus_interface=_NM_ACCESSPOINT_IFACE) 378 379 self._bus.remove_signal_receiver(self.__device_state_changed_cb, 380 signal_name='StateChanged', 381 path=self._device.object_path, 382 dbus_interface=_NM_DEVICE_IFACE) 383 self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, 384 signal_name='PropertiesChanged', 385 path=self._device.object_path, 386 dbus_interface=_NM_WIRELESS_IFACE) 267 387 268 388 class ActivityView(hippo.CanvasBox): 269 389 def __init__(self, model): … … class ActivityView(hippo.CanvasBox): 364 484 self._update_palette() 365 485 366 486 def _joined_changed_cb(self, widget, event): 367 logging.debug('ActivityView._joined_changed_cb : AAAA!!!!')487 logging.debug('ActivityView._joined_changed_cb') 368 488 369 489 _AUTOSEARCH_TIMEOUT = 1000 370 490 … … class MeshToolbar(gtk.Toolbar): 436 556 self.search_entry.activate() 437 557 return False 438 558 559 class DeviceObserver(object): 560 def __init__(self, box, device): 561 self._box = box 562 self._bus = dbus.SystemBus() 563 self._device = device 564 565 wireless = dbus.Interface(self._device, _NM_WIRELESS_IFACE) 566 wireless.GetAccessPoints(reply_handler=self._get_access_points_reply_cb, 567 error_handler=self._get_access_points_error_cb) 568 569 self._bus.add_signal_receiver(self.__access_point_added_cb, 570 signal_name='AccessPointAdded', 571 path=device.object_path, 572 dbus_interface=_NM_WIRELESS_IFACE) 573 self._bus.add_signal_receiver(self.__access_point_removed_cb, 574 signal_name='AccessPointRemoved', 575 path=device.object_path, 576 dbus_interface=_NM_WIRELESS_IFACE) 577 578 def _get_access_points_reply_cb(self, access_points_o): 579 for ap_o in access_points_o: 580 ap = self._bus.get_object(_NM_SERVICE, ap_o) 581 self._box.add_access_point(self._device, ap) 582 583 def _get_access_points_error_cb(self, err): 584 logging.error('Failed to get access points: %s', err) 585 586 def __access_point_added_cb(self, access_point_o): 587 ap = self._bus.get_object(_NM_SERVICE, access_point_o) 588 self._box.add_access_point(self._device, ap) 589 590 def __access_point_removed_cb(self, access_point_o): 591 self._box.remove_access_point(access_point_o) 592 593 def disconnect(self): 594 self._bus.remove_signal_receiver(self.__access_point_added_cb, 595 signal_name='AccessPointAdded', 596 path=self._device.object_path, 597 dbus_interface=_NM_WIRELESS_IFACE) 598 self._bus.remove_signal_receiver(self.__access_point_removed_cb, 599 signal_name='AccessPointRemoved', 600 path=self._device.object_path, 601 dbus_interface=_NM_WIRELESS_IFACE) 602 603 class NetworkManagerObserver(object): 604 def __init__(self, box): 605 self._box = box 606 self._bus = dbus.SystemBus() 607 self._devices = {} 608 self._netmgr = None 609 610 def listen(self): 611 try: 612 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) 613 self._netmgr = dbus.Interface(obj, _NM_IFACE) 614 except dbus.DBusException: 615 logging.debug('%s service not available', _NM_SERVICE) 616 return 617 618 self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb, 619 error_handler=self.__get_devices_error_cb) 620 621 self._bus.add_signal_receiver(self.__device_added_cb, 622 signal_name='DeviceAdded', 623 dbus_interface=_NM_IFACE) 624 self._bus.add_signal_receiver(self.__device_removed_cb, 625 signal_name='DeviceRemoved', 626 dbus_interface=_NM_IFACE) 627 628 settings = network.get_settings() 629 if settings is not None: 630 settings.secrets_request.connect(self.__secrets_request_cb) 631 632 def __secrets_request_cb(self, **kwargs): 633 # FIXME It would be better to do all of this async, but I cannot think 634 # of a good way to. NM could really use some love here. 635 636 netmgr_props = dbus.Interface( 637 self._netmgr, 'org.freedesktop.DBus.Properties') 638 active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') 639 640 for conn_o in active_connections_o: 641 obj = self._bus.get_object(_NM_IFACE, conn_o) 642 props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') 643 ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') 644 645 ap_view = self._box.access_points[ap_o] 646 ap_view.create_keydialog(kwargs['response']) 647 648 def __get_devices_reply_cb(self, devices_o): 649 for dev_o in devices_o: 650 self._check_device(dev_o) 651 652 def __get_devices_error_cb(self, err): 653 logging.error('Failed to get devices: %s', err) 654 655 def _check_device(self, device_o): 656 device = self._bus.get_object(_NM_SERVICE, device_o) 657 props = dbus.Interface(device, 'org.freedesktop.DBus.Properties') 658 659 device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') 660 if device_type == network.DEVICE_TYPE_802_11_WIRELESS: 661 self._devices[device_o] = DeviceObserver(self._box, device) 662 663 def _get_device_path_error_cb(self, err): 664 logging.error('Failed to get device type: %s', err) 665 666 def __device_added_cb(self, device_o): 667 self._check_device(device_o) 668 669 def __device_removed_cb(self, device_o): 670 if device_o in self._devices: 671 observer = self._devices[device_o] 672 observer.disconnect() 673 del self._devices[device_o] 674 439 675 class MeshBox(gtk.VBox): 440 676 __gtype_name__ = 'SugarMeshBox' 677 441 678 def __init__(self): 679 logging.debug("STARTUP: Loading the mesh view") 680 442 681 gobject.GObject.__init__(self) 443 682 444 self._model = shellmodel.get_instance().get_mesh() 683 self.access_points = {} 684 685 self._model = neighborhood.get_model() 445 686 self._buddies = {} 446 687 self._activities = {} 447 self._access_points = {}448 688 self._mesh = {} 449 689 self._buddy_to_activity = {} 450 690 self._suspended = True … … class MeshBox(gtk.VBox): 480 720 self._model.connect('activity-added', self._activity_added_cb) 481 721 self._model.connect('activity-removed', self._activity_removed_cb) 482 722 483 for ap_model in self._model.get_access_points(): 484 self._add_access_point(ap_model) 485 486 self._model.connect('access-point-added', 487 self._access_point_added_cb) 488 self._model.connect('access-point-removed', 489 self._access_point_removed_cb) 490 491 if self._model.get_mesh(): 492 self.__mesh_added_cb(self._model, self._model.get_mesh()) 493 494 self._model.connect('mesh-added', self.__mesh_added_cb) 495 self._model.connect('mesh-removed', self.__mesh_removed_cb) 496 497 def __mesh_added_cb(self, model, meshdev): 498 self._add_mesh_icon(meshdev, 1) 499 self._add_mesh_icon(meshdev, 6) 500 self._add_mesh_icon(meshdev, 11) 501 502 def __mesh_removed_cb(self, model): 503 self._remove_mesh_icon(1) 504 self._remove_mesh_icon(6) 505 self._remove_mesh_icon(11) 723 netmgr_observer = NetworkManagerObserver(self) 724 netmgr_observer.listen() 506 725 507 726 def do_size_allocate(self, allocation): 508 727 width = allocation.width … … class MeshBox(gtk.VBox): 534 753 def _activity_removed_cb(self, model, activity_model): 535 754 self._remove_activity(activity_model) 536 755 537 def _access_point_added_cb(self, model, ap_model):538 self._add_access_point(ap_model)539 540 def _access_point_removed_cb(self, model, ap_model):541 self._remove_access_point(ap_model)542 543 def _add_mesh_icon(self, meshdev, channel):544 if self._mesh.has_key(channel):545 self._remove_mesh_icon(channel)546 if not meshdev:547 return548 self._mesh[channel] = MeshDeviceView(meshdev, channel)549 self._layout.add(self._mesh[channel])550 551 def _remove_mesh_icon(self, channel):552 if not self._mesh.has_key(channel):553 return554 self._layout.remove(self._mesh[channel])555 del self._mesh[channel]556 557 756 def _add_alone_buddy(self, buddy_model): 558 757 icon = BuddyIcon(buddy_model) 559 758 if buddy_model.is_owner(): … … class MeshBox(gtk.VBox): 563 762 if hasattr(icon, 'set_filter'): 564 763 icon.set_filter(self._query) 565 764 566 self._buddies[buddy_model.get_ key()] = icon765 self._buddies[buddy_model.get_buddy().object_path()] = icon 567 766 568 767 def _remove_alone_buddy(self, buddy_model): 569 icon = self._buddies[buddy_model.get_ key()]768 icon = self._buddies[buddy_model.get_buddy().object_path()] 570 769 self._layout.remove(icon) 571 del self._buddies[buddy_model.get_ key()]770 del self._buddies[buddy_model.get_buddy().object_path()] 572 771 icon.destroy() 573 772 574 773 def _remove_buddy(self, buddy_model): 575 key = buddy_model.get_key()576 if self._buddies.has_key( key):774 object_path = buddy_model.get_buddy().object_path() 775 if self._buddies.has_key(object_path): 577 776 self._remove_alone_buddy(buddy_model) 578 777 else: 579 778 for activity in self._activities.values(): 580 if activity.has_buddy_icon( key):581 activity.remove_buddy_icon( key)779 if activity.has_buddy_icon(object_path): 780 activity.remove_buddy_icon(object_path) 582 781 583 782 def _move_buddy(self, buddy_model, activity_model): 584 783 self._remove_buddy(buddy_model) … … class MeshBox(gtk.VBox): 589 788 activity = self._activities[activity_model.get_id()] 590 789 591 790 icon = BuddyIcon(buddy_model, style.STANDARD_ICON_SIZE) 592 activity.add_buddy_icon(buddy_model.get_ key(), icon)791 activity.add_buddy_icon(buddy_model.get_buddy().object_path(), icon) 593 792 594 793 if hasattr(icon, 'set_filter'): 595 794 icon.set_filter(self._query) … … class MeshBox(gtk.VBox): 609 808 del self._activities[activity_model.get_id()] 610 809 icon.destroy() 611 810 612 def _add_access_point(self, ap_model): 613 meshdev = self._model.get_mesh() 614 icon = AccessPointView(ap_model, meshdev) 811 def add_access_point(self, device, ap): 812 icon = AccessPointView(device, ap) 615 813 self._layout.add(icon) 616 814 617 815 if hasattr(icon, 'set_filter'): 618 816 icon.set_filter(self._query) 619 817 620 self. _access_points[ap_model.get_id()] = icon818 self.access_points[ap.object_path] = icon 621 819 622 def _remove_access_point(self, ap_model): 623 icon = self._access_points[ap_model.get_id()] 624 self._layout.remove(icon) 625 del self._access_points[ap_model.get_id()] 820 def remove_access_point(self, ap_o): 821 if ap_o in self.access_points: 822 icon = self.access_points[ap_o] 823 icon.disconnect() 824 self._layout.remove(icon) 825 del self.access_points[ap_o] 826 else: 827 logging.error('Can not remove access point %s' % ap_o) 626 828 627 829 def suspend(self): 628 830 if not self._suspended: 629 831 self._suspended = True 630 for ap in self. _access_points.values():832 for ap in self.access_points.values(): 631 833 ap.props.paused = True 632 834 633 835 def resume(self): 634 836 if self._suspended: 635 837 self._suspended = False 636 for ap in self. _access_points.values():838 for ap in self.access_points.values(): 637 839 ap.props.paused = False 638 840 639 841 def _toolbar_query_changed_cb(self, toolbar, query): -
new file src/view/home/keydialog.py
diff --git a/src/view/home/keydialog.py b/src/view/home/keydialog.py new file mode 100644 index 0000000..92e8f40
- + 1 # Copyright (C) 2006-2007 Red Hat, Inc. 2 # 3 # This program is free software; you can redistribute it and/or modify 4 # it under the terms of the GNU General Public License as published by 5 # the Free Software Foundation; either version 2 of the License, or 6 # (at your option) any later version. 7 # 8 # This program is distributed in the hope that it will be useful, 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # GNU General Public License for more details. 12 # 13 # You should have received a copy of the GNU General Public License 14 # along with this program; if not, write to the Free Software 15 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 17 import md5 18 from gettext import gettext as _ 19 20 import gtk 21 import dbus 22 23 from model import network 24 from model.network import Secrets 25 26 IW_AUTH_ALG_OPEN_SYSTEM = 'open' 27 IW_AUTH_ALG_SHARED_KEY = 'shared' 28 29 def string_is_hex(key): 30 is_hex = True 31 for c in key: 32 if not 'a' <= c.lower() <= 'f' and not '0' <= c <= '9': 33 is_hex = False 34 return is_hex 35 36 def string_is_ascii(string): 37 try: 38 string.encode('ascii') 39 return True 40 except UnicodeEncodeError: 41 return False 42 43 def string_to_hex(passphrase): 44 key = '' 45 for c in passphrase: 46 key += '%02x' % ord(c) 47 return key 48 49 def hash_passphrase(passphrase): 50 # passphrase must have a length of 64 51 if len(passphrase) > 64: 52 passphrase = passphrase[:64] 53 elif len(passphrase) < 64: 54 while len(passphrase) < 64: 55 passphrase += passphrase[:64 - len(passphrase)] 56 passphrase = md5.new(passphrase).digest() 57 return string_to_hex(passphrase)[:26] 58 59 class CanceledKeyRequestError(dbus.DBusException): 60 def __init__(self): 61 dbus.DBusException.__init__(self) 62 self._dbus_error_name = network.NM_SETTINGS_IFACE + '.CanceledError' 63 64 class KeyDialog(gtk.Dialog): 65 def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): 66 gtk.Dialog.__init__(self, flags=gtk.DIALOG_MODAL) 67 self.set_title("Wireless Key Required") 68 69 self._response = response 70 self._entry = None 71 self._ssid = ssid 72 self._flags = flags 73 self._wpa_flags = wpa_flags 74 self._rsn_flags = rsn_flags 75 self._dev_caps = dev_caps 76 77 self.set_has_separator(False) 78 79 label = gtk.Label("A wireless encryption key is required for\n" \ 80 " the wireless network '%s'." % self._ssid) 81 self.vbox.pack_start(label) 82 83 self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, 84 gtk.STOCK_OK, gtk.RESPONSE_OK) 85 self.set_default_response(gtk.RESPONSE_OK) 86 self.set_has_separator(True) 87 88 def add_key_entry(self): 89 self._entry = gtk.Entry() 90 self._entry.connect('changed', self._update_response_sensitivity) 91 self._entry.connect('activate', self._entry_activate_cb) 92 self.vbox.pack_start(self._entry) 93 self.vbox.set_spacing(6) 94 self.vbox.show_all() 95 96 self._update_response_sensitivity() 97 self._entry.grab_focus() 98 99 def _entry_activate_cb(self, entry): 100 self.response(gtk.RESPONSE_OK) 101 102 def create_security(self): 103 raise NotImplementedError 104 105 def get_response_object(self): 106 return self._response 107 108 WEP_PASSPHRASE = 1 109 WEP_HEX = 2 110 WEP_ASCII = 3 111 112 class WEPKeyDialog(KeyDialog): 113 def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): 114 KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags, 115 dev_caps, response) 116 117 # WEP key type 118 self.key_store = gtk.ListStore(str, int) 119 self.key_store.append(["Passphrase (128-bit)", WEP_PASSPHRASE]) 120 self.key_store.append(["Hex (40/128-bit)", WEP_HEX]) 121 self.key_store.append(["ASCII (40/128-bit)", WEP_ASCII]) 122 123 self.key_combo = gtk.ComboBox(self.key_store) 124 cell = gtk.CellRendererText() 125 self.key_combo.pack_start(cell, True) 126 self.key_combo.add_attribute(cell, 'text', 0) 127 self.key_combo.set_active(0) 128 self.key_combo.connect('changed', self._key_combo_changed_cb) 129 130 hbox = gtk.HBox() 131 hbox.pack_start(gtk.Label(_("Key Type:"))) 132 hbox.pack_start(self.key_combo) 133 hbox.show_all() 134 self.vbox.pack_start(hbox) 135 136 # Key entry field 137 self.add_key_entry() 138 139 # WEP authentication mode 140 self.auth_store = gtk.ListStore(str, str) 141 self.auth_store.append(["Open System", IW_AUTH_ALG_OPEN_SYSTEM]) 142 self.auth_store.append(["Shared Key", IW_AUTH_ALG_SHARED_KEY]) 143 144 self.auth_combo = gtk.ComboBox(self.auth_store) 145 cell = gtk.CellRendererText() 146 self.auth_combo.pack_start(cell, True) 147 self.auth_combo.add_attribute(cell, 'text', 0) 148 self.auth_combo.set_active(0) 149 150 hbox = gtk.HBox() 151 hbox.pack_start(gtk.Label(_("Authentication Type:"))) 152 hbox.pack_start(self.auth_combo) 153 hbox.show_all() 154 155 self.vbox.pack_start(hbox) 156 157 def _key_combo_changed_cb(self, widget): 158 self._update_response_sensitivity() 159 160 def _get_security(self): 161 key = self._entry.get_text() 162 163 it = self.key_combo.get_active_iter() 164 (key_type, ) = self.key_store.get(it, 1) 165 166 if key_type == WEP_PASSPHRASE: 167 key = hash_passphrase(key) 168 elif key_type == WEP_ASCII: 169 key = string_to_hex(key) 170 171 it = self.auth_combo.get_active_iter() 172 (auth_alg, ) = self.auth_store.get(it, 1) 173 174 return (key, auth_alg) 175 176 def print_security(self): 177 (key, auth_alg) = self._get_security() 178 print "Key: %s" % key 179 print "Auth: %d" % auth_alg 180 181 def create_security(self): 182 (key, auth_alg) = self._get_security() 183 secrets = Secrets() 184 secrets.wep_key = key 185 secrets.auth_alg = auth_alg 186 return secrets 187 188 def _update_response_sensitivity(self, ignored=None): 189 key = self._entry.get_text() 190 it = self.key_combo.get_active_iter() 191 (key_type, ) = self.key_store.get(it, 1) 192 193 valid = False 194 if key_type == WEP_PASSPHRASE: 195 # As the md5 passphrase can be of any length and has no indicator, 196 # we cannot check for the validity of the input. 197 if len(key) > 0: 198 valid = True 199 elif key_type == WEP_ASCII: 200 if len(key) == 5 or len(key) == 13: 201 valid = string_is_ascii(key) 202 elif key_type == WEP_HEX: 203 if len(key) == 10 or len(key) == 26: 204 valid = string_is_hex(key) 205 206 self.set_response_sensitive(gtk.RESPONSE_OK, valid) 207 208 class WPAKeyDialog(KeyDialog): 209 def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): 210 KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags, 211 dev_caps, response) 212 self.add_key_entry() 213 214 self.store = gtk.ListStore(str) 215 self.store.append([_("WPA & WPA2 Personal")]) 216 217 self.combo = gtk.ComboBox(self.store) 218 cell = gtk.CellRendererText() 219 self.combo.pack_start(cell, True) 220 self.combo.add_attribute(cell, 'text', 0) 221 self.combo.set_active(0) 222 223 self.hbox = gtk.HBox() 224 self.hbox.pack_start(gtk.Label(_("Wireless Security:"))) 225 self.hbox.pack_start(self.combo) 226 self.hbox.show_all() 227 228 self.vbox.pack_start(self.hbox) 229 230 def _get_security(self): 231 ssid = self._ssid 232 key = self._entry.get_text() 233 is_hex = string_is_hex(key) 234 235 real_key = None 236 if len(key) == 64 and is_hex: 237 # Hex key 238 real_key = key 239 elif len(key) >= 8 and len(key) <= 63: 240 # passphrase 241 from subprocess import Popen, PIPE 242 p = Popen(['/usr/sbin/wpa_passphrase', ssid, key], stdout=PIPE) 243 for line in p.stdout: 244 if line.strip().startswith("psk="): 245 real_key = line.strip()[4:] 246 if p.wait() != 0: 247 raise RuntimeError("Error hashing passphrase") 248 if real_key and len(real_key) != 64: 249 real_key = None 250 251 if not real_key: 252 raise RuntimeError("Invalid key") 253 254 return real_key 255 256 def print_security(self): 257 key = self._get_security() 258 print "Key: %s" % key 259 260 def create_security(self): 261 secrets = Secrets() 262 secrets.psk = self._get_security() 263 return secrets 264 265 def _update_response_sensitivity(self, ignored=None): 266 key = self._entry.get_text() 267 is_hex = string_is_hex(key) 268 269 valid = False 270 if len(key) == 64 and is_hex: 271 # hex key 272 valid = True 273 elif len(key) >= 8 and len(key) <= 63: 274 # passphrase 275 valid = True 276 self.set_response_sensitive(gtk.RESPONSE_OK, valid) 277 return False 278 279 def create(ssid, flags, wpa_flags, rsn_flags, dev_caps, response): 280 if wpa_flags == network.NM_802_11_AP_SEC_NONE and \ 281 rsn_flags == network.NM_802_11_AP_SEC_NONE: 282 key_dialog = WEPKeyDialog(ssid, flags, wpa_flags, rsn_flags, 283 dev_caps, response) 284 else: 285 key_dialog = WPAKeyDialog(ssid, flags, wpa_flags, rsn_flags, 286 dev_caps, response) 287 288 key_dialog.connect("response", _key_dialog_response_cb) 289 key_dialog.connect("destroy", _key_dialog_destroy_cb) 290 key_dialog.show_all() 291 292 def _key_dialog_destroy_cb(key_dialog, data=None): 293 _key_dialog_response_cb(key_dialog, gtk.RESPONSE_CANCEL) 294 295 def _key_dialog_response_cb(key_dialog, response_id): 296 response = key_dialog.get_response_object() 297 secrets = None 298 if response_id == gtk.RESPONSE_OK: 299 secrets = key_dialog.create_security() 300 301 if response_id in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_NONE]: 302 # key dialog dialog was canceled; send the error back to NM 303 response.set_error(CanceledKeyRequestError()) 304 elif response_id == gtk.RESPONSE_OK: 305 if not secrets: 306 raise RuntimeError("Invalid security arguments.") 307 response.set_secrets(secrets) 308 else: 309 raise RuntimeError("Unhandled key dialog response %d" % response_id) 310 311 key_dialog.destroy()