#!/usr/bin/env python """ netentry_curses -- everyone's favorite networks settings dialogs... in text form! """ # Copyright (C) 2009 Andrew Psaltis # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. import urwid from curses_misc import TextDialog,DynWrap,MaskingEdit,ComboBox,error import wicd.misc as misc from wicd.misc import noneToString, stringToNone, noneToBlankString, to_bool from wicd.translations import language, _ import os daemon = None wired = None wireless = None # Call this first! def dbus_init(dbus_ifaces): global daemon,wired,wireless daemon = dbus_ifaces['daemon'] wired = dbus_ifaces['wired'] wireless = dbus_ifaces['wireless'] # Both the wired and the wireless settings preferences dialogs use some of the # same fields. # This will be used to produce the individual network settings dialogs way far below class AdvancedSettingsDialog(urwid.WidgetWrap): def __init__(self): self.ui=None static_ip_t = _('Use Static IPs') ip_t = ('editcp',_('IP')+': ') netmask_t = ('editcp',_('Netmask')+':') gateway_t = ('editcp',_('Gateway')+':') use_static_dns_t = _('Use Static DNS') use_global_dns_t = _('Use global DNS servers') dns_dom_t = ('editcp',_('DNS domain')+': ') search_dom_t = ('editcp',_('Search domain')+':') dns1_t = ('editcp',_('DNS server')+ ' 1'+':'+' '*8) dns2_t = ('editcp',_('DNS server')+ ' 2'+':'+' '*8) dns3_t = ('editcp',_('DNS server')+ ' 3'+':'+' '*8) use_dhcp_h_t = _('Use DHCP Hostname') dhcp_h_t = ('editcp',_('DHCP Hostname')+': ') cancel_t = _('Cancel') ok_t = _('OK') self.static_ip_cb = urwid.CheckBox(static_ip_t, on_state_change=self.static_ip_toggle) self.ip_edit = DynWrap(urwid.Edit(ip_t),False) self.netmask_edit = DynWrap(urwid.Edit(netmask_t),False) self.gateway_edit = DynWrap(urwid.Edit(gateway_t),False) self.static_dns_cb = DynWrap(urwid.CheckBox(use_static_dns_t, on_state_change=self.dns_toggle),True,('body','editnfc'),None) self.global_dns_cb = DynWrap(urwid.CheckBox(use_global_dns_t, on_state_change=self.dns_toggle),False,('body','editnfc'),None) self.checkb_cols = urwid.Columns([self.static_dns_cb, self.global_dns_cb]) self.dns_dom_edit = DynWrap(urwid.Edit(dns_dom_t) ,False) self.search_dom_edit = DynWrap(urwid.Edit(search_dom_t),False) self.dns1 = DynWrap(urwid.Edit(dns1_t) ,False) self.dns2 = DynWrap(urwid.Edit(dns2_t) ,False) self.dns3 = DynWrap(urwid.Edit(dns3_t) ,False) self.use_dhcp_h = urwid.CheckBox(use_dhcp_h_t,False,on_state_change=self.use_dhcp_h_toggle) self.dhcp_h = DynWrap(urwid.Edit(dhcp_h_t),False) _blank = urwid.Text('') walker = urwid.SimpleListWalker([self.static_ip_cb, self.ip_edit, self.netmask_edit, self.gateway_edit, _blank, self.checkb_cols, self.dns_dom_edit,self.search_dom_edit, self.dns1,self.dns2,self.dns3, _blank, self.use_dhcp_h, self.dhcp_h, _blank ]) self._listbox = urwid.ListBox(walker) self._frame = urwid.Frame(self._listbox) self.__super.__init__(self._frame) def use_dhcp_h_toggle(self,checkb,new_state,user_data=None): self.dhcp_h.set_sensitive(new_state) def static_ip_toggle(self,checkb,new_state,user_data=None): for w in [ self.ip_edit,self.netmask_edit,self.gateway_edit ]: w.set_sensitive(new_state) self.static_dns_cb.set_state(new_state) self.static_dns_cb.set_sensitive(not new_state) if new_state: self.checkb_cols.set_focus(self.global_dns_cb) else: self.checkb_cols.set_focus(self.static_dns_cb) def dns_toggle(self,checkb,new_state,user_data=None): if checkb == self.static_dns_cb.get_w(): for w in [ self.dns_dom_edit,self.search_dom_edit, self.dns1,self.dns2,self.dns3 ]: w.set_sensitive(new_state) if not new_state: self.global_dns_cb.set_state(False,do_callback=False) self.global_dns_cb.set_sensitive(new_state) # use_global_dns_cb is DynWrapped if checkb == self.global_dns_cb.get_w(): for w in [self.dns_dom_edit,self.search_dom_edit, self.dns1,self.dns2,self.dns3 ]: w.set_sensitive(not new_state) # Code totally yanked from netentry.py def save_settings(self): """ Save settings common to wired and wireless settings dialogs. """ if self.static_ip_cb.get_state(): for i in [self.ip_edit,self.netmask_edit,self.gateway_edit]: i.set_edit_text(i.get_edit_text().strip()) self.set_net_prop("ip", noneToString(self.ip_edit.get_edit_text())) self.set_net_prop("netmask", noneToString(self.netmask_edit.get_edit_text())) self.set_net_prop("gateway", noneToString(self.gateway_edit.get_edit_text())) else: self.set_net_prop("ip", '') self.set_net_prop("netmask", '') self.set_net_prop("gateway", '') if self.static_dns_cb.get_state() and \ not self.global_dns_cb.get_state(): self.set_net_prop('use_static_dns', True) self.set_net_prop('use_global_dns', False) # Strip addressses before checking them in the daemon. for i in [self.dns1, self.dns2, self.dns3,self.dns_dom_edit, self.search_dom_edit]: i.set_edit_text(i.get_edit_text().strip()) self.set_net_prop('dns_domain', noneToString(self.dns_dom_edit.get_edit_text())) self.set_net_prop("search_domain", noneToString(self.search_dom_edit.get_edit_text())) self.set_net_prop("dns1", noneToString(self.dns1.get_edit_text())) self.set_net_prop("dns2", noneToString(self.dns2.get_edit_text())) self.set_net_prop("dns3", noneToString(self.dns3.get_edit_text())) elif self.static_dns_cb.get_state() and \ self.global_dns_cb.get_state(): self.set_net_prop('use_static_dns', True) self.set_net_prop('use_global_dns', True) else: self.set_net_prop('use_static_dns', False) self.set_net_prop('use_global_dns', False) self.set_net_prop('dns_domain', '') self.set_net_prop("search_domain", '') self.set_net_prop("dns1", '') self.set_net_prop("dns2", '') self.set_net_prop("dns3", '') self.set_net_prop('dhcphostname',self.dhcp_h.get_edit_text()) self.set_net_prop('usedhcphostname',self.use_dhcp_h.get_state()) # Prevent comboboxes from dying. def ready_widgets(self,ui,body): self.ui = ui self.body = body self.encryption_combo.build_combobox(body,ui,14) self.change_encrypt_method() def combo_on_change(self,combobox,new_index,user_data=None): self.change_encrypt_method() # More or less ripped from netentry.py def change_encrypt_method(self): #self.lbox_encrypt = urwid.ListBox() self.encryption_info = {} wid,ID = self.encryption_combo.get_focus() methods = self.encrypt_types if self._w.body.body.__contains__(self.pile_encrypt): self._w.body.body.pop(self._w.body.body.__len__()-1) # If nothing is selected, select the first entry. if ID == -1: self.encryption_combo.set_focus(0) ID = 0 theList = [] for type_ in ['required', 'optional']: fields = methods[ID][type_] for field in fields: try: edit = MaskingEdit(('editcp',language[field[1].lower().replace(' ','_')]+': ')) except KeyError: edit = MaskingEdit(('editcp',field[1].replace(' ','_')+': ')) edit.set_mask_mode('no_focus') theList.append(edit) # Add the data to any array, so that the information # can be easily accessed by giving the name of the wanted # data. self.encryption_info[field[0]] = [edit, type_] if self.wired: edit.set_edit_text(noneToBlankString( wired.GetWiredProperty(field[0]))) else: edit.set_edit_text(noneToBlankString( wireless.GetWirelessProperty(self.networkid, field[0]))) #FIXME: This causes the entire pile to light up upon use. # Make this into a listbox? self.pile_encrypt = DynWrap(urwid.Pile(theList),attrs=('editbx','editnfc')) self.pile_encrypt.set_sensitive(self.encryption_chkbox.get_state()) self._w.body.body.insert(self._w.body.body.__len__(),self.pile_encrypt) #self._w.body.body.append(self.pile_encrypt) def encryption_toggle(self,chkbox,new_state,user_data=None): self.encryption_combo.set_sensitive(new_state) self.pile_encrypt.set_sensitive(new_state) class WiredSettingsDialog(AdvancedSettingsDialog): def __init__(self,name,parent): global wired, daemon AdvancedSettingsDialog.__init__(self) self.wired = True self.set_default = urwid.CheckBox(_('Use as default profile (overwrites any previous default)')) #self.cur_default = # Add widgets to listbox self._w.body.body.append(self.set_default) self.parent = parent encryption_t = _('Use Encryption') self.encryption_chkbox = urwid.CheckBox(encryption_t,on_state_change=self.encryption_toggle) self.encryption_combo = ComboBox(callback=self.combo_on_change) self.pile_encrypt = None # _w is a Frame, _w.body is a ListBox, _w.body.body is the ListWalker :-) self._listbox.body.append(self.encryption_chkbox) self._listbox.body.append(self.encryption_combo) self.encrypt_types = misc.LoadEncryptionMethods(wired = True) self.set_values() self.prof_name = name title = _('Configuring preferences for wired profile "$A"').replace('$A',self.prof_name) self._w.header = urwid.Text( ('header',title),align='right' ) self.set_values() def set_net_prop(self,option,value): wired.SetWiredProperty(option,value) def set_values(self): self.ip_edit.set_edit_text(self.format_entry("ip")) self.netmask_edit.set_edit_text(self.format_entry("netmask")) self.gateway_edit.set_edit_text(self.format_entry("gateway")) self.global_dns_cb.set_state(bool(wired.GetWiredProperty('use_global_dns'))) self.static_dns_cb.set_state(bool(wired.GetWiredProperty('use_static_dns'))) # Set static ip checkbox. Forgot to do this the first time. if stringToNone(self.ip_edit.get_edit_text()): self.static_ip_cb.set_state(True) self.dns1.set_edit_text(self.format_entry( "dns1")) self.dns2.set_edit_text(self.format_entry( "dns2")) self.dns3.set_edit_text(self.format_entry( "dns3")) self.dns_dom_edit.set_edit_text(self.format_entry("dns_domain")) self.search_dom_edit.set_edit_text(self.format_entry("search_domain")) self.set_default.set_state(to_bool(wired.GetWiredProperty("default"))) # Throw the encryption stuff into a list list = [] activeID = -1 # Set the menu to this item when we are done for x, enc_type in enumerate(self.encrypt_types): list.append(enc_type['name']) if enc_type['type'] == wired.GetWiredProperty("enctype"): activeID = x self.encryption_combo.set_list(list) self.encryption_combo.set_focus(activeID) if wired.GetWiredProperty("encryption_enabled"): self.encryption_chkbox.set_state(True,do_callback=False) self.encryption_combo.set_sensitive(True) #self.lbox_encrypt_info.set_sensitive(True) else: self.encryption_combo.set_focus(0) self.encryption_combo.set_sensitive(False) self.change_encrypt_method() dhcphname = wired.GetWiredProperty("dhcphostname") if dhcphname is None: dhcphname = os.uname()[1] self.use_dhcp_h.set_state(bool(wired.GetWiredProperty('usedhcphostname'))) self.dhcp_h.set_sensitive(self.use_dhcp_h.get_state()) self.dhcp_h.set_edit_text(unicode(dhcphname)) def save_settings(self): # Check encryption info if self.encryption_chkbox.get_state(): encrypt_info = self.encryption_info encrypt_methods = self.encrypt_types self.set_net_prop("enctype", encrypt_methods[self.encryption_combo.get_focus()[1] ]['type']) self.set_net_prop("encryption_enabled", True) # Make sure all required fields are filled in. for entry_info in encrypt_info.itervalues(): if entry_info[0].get_edit_text() == "" \ and entry_info[1] == 'required': error(self.ui, self.parent,"%s (%s)" \ % (_('Required encryption information is missing.'), entry_info[0].get_caption()[0:-2] ) ) return False for entry_key, entry_info in encrypt_info.iteritems(): self.set_net_prop(entry_key, noneToString(entry_info[0]. get_edit_text())) else: self.set_net_prop("enctype", "None") self.set_net_prop("encryption_enabled", False) AdvancedSettingsDialog.save_settings(self) if self.set_default.get_state(): wired.UnsetWiredDefault() if self.set_default.get_state(): bool = True else: bool = False wired.SetWiredProperty("default",bool) wired.SaveWiredNetworkProfile(self.prof_name) return True def format_entry(self, label): """ Helper method to fetch and format wired properties. """ return noneToBlankString(wired.GetWiredProperty(label)) def prerun(self,ui,dim,display): pass ######################################## class WirelessSettingsDialog(AdvancedSettingsDialog): def __init__(self,networkID,parent): global wireless, daemon AdvancedSettingsDialog.__init__(self) self.wired = False self.networkid = networkID self.parent = parent global_settings_t = _('Use these settings for all networks sharing this essid') encryption_t = _('Use Encryption') autoconnect_t = _('Automatically connect to this network') self.global_settings_chkbox = urwid.CheckBox(global_settings_t) self.encryption_chkbox = urwid.CheckBox(encryption_t,on_state_change=self.encryption_toggle) self.encryption_combo = ComboBox(callback=self.combo_on_change) self.autoconnect_chkbox = urwid.CheckBox(autoconnect_t) self.pile_encrypt = None # _w is a Frame, _w.body is a ListBox, _w.body.body is the ListWalker :-) self._listbox.body.append(self.global_settings_chkbox) self._listbox.body.append(self.autoconnect_chkbox) self._listbox.body.append(self.encryption_chkbox) self._listbox.body.append(self.encryption_combo) self.encrypt_types = misc.LoadEncryptionMethods() self.set_values() title = _('Configuring preferences for wireless network "$A" ($B)').replace('$A',wireless.GetWirelessProperty(networkID,'essid')).replace('$B',wireless.GetWirelessProperty(networkID,'bssid')) self._w.header = urwid.Text(('header',title),align='right' ) def set_values(self): """ Set the various network settings to the right values. """ networkID = self.networkid self.ip_edit.set_edit_text(self.format_entry(networkID,"ip")) self.netmask_edit.set_edit_text(self.format_entry(networkID,"netmask")) self.gateway_edit.set_edit_text(self.format_entry(networkID,"gateway")) self.global_dns_cb.set_state(bool(wireless.GetWirelessProperty(networkID, 'use_global_dns'))) self.static_dns_cb.set_state(bool(wireless.GetWirelessProperty(networkID, 'use_static_dns'))) if stringToNone(self.ip_edit.get_edit_text()): self.static_ip_cb.set_state(True) self.dns1.set_edit_text(self.format_entry(networkID, "dns1")) self.dns2.set_edit_text(self.format_entry(networkID, "dns2")) self.dns3.set_edit_text(self.format_entry(networkID, "dns3")) self.dns_dom_edit.set_edit_text(self.format_entry(networkID, "dns_domain")) self.search_dom_edit.set_edit_text(self.format_entry(networkID, "search_domain")) self.autoconnect_chkbox.set_state(to_bool(self.format_entry(networkID, "automatic"))) #self.reset_static_checkboxes() self.encryption_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID, 'encryption')),do_callback=False) self.global_settings_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID ,'use_settings_globally'))) # Throw the encryption stuff into a list list = [] activeID = -1 # Set the menu to this item when we are done for x, enc_type in enumerate(self.encrypt_types): list.append(enc_type['name']) if enc_type['type'] == wireless.GetWirelessProperty(networkID, "enctype"): activeID = x self.encryption_combo.set_list(list) self.encryption_combo.set_focus(activeID) if activeID != -1: self.encryption_chkbox.set_state(True,do_callback=False) self.encryption_combo.set_sensitive(True) #self.lbox_encrypt_info.set_sensitive(True) else: self.encryption_combo.set_focus(0) self.change_encrypt_method() dhcphname = wireless.GetWirelessProperty(networkID,"dhcphostname") if dhcphname is None: dhcphname = os.uname()[1] self.use_dhcp_h.set_state(bool(wireless.GetWirelessProperty(networkID,'usedhcphostname'))) self.dhcp_h.set_sensitive(self.use_dhcp_h.get_state()) self.dhcp_h.set_edit_text(unicode(dhcphname)) def set_net_prop(self, option, value): """ Sets the given option to the given value for this network. """ wireless.SetWirelessProperty(self.networkid, option, value) def format_entry(self, networkid, label): """ Helper method for fetching/formatting wireless properties. """ return noneToBlankString(wireless.GetWirelessProperty(networkid, label)) # Ripped from netentry.py def save_settings(self): # Check encryption info if self.encryption_chkbox.get_state(): encrypt_info = self.encryption_info encrypt_methods = self.encrypt_types self.set_net_prop("enctype", encrypt_methods[self.encryption_combo.get_focus()[1] ]['type']) # Make sure all required fields are filled in. for entry_info in encrypt_info.itervalues(): if entry_info[0].get_edit_text() == "" \ and entry_info[1] == 'required': error(self.ui, self.parent,"%s (%s)" \ % (_('Required encryption information is missing.'), entry_info[0].get_caption()[0:-2] ) ) return False for entry_key, entry_info in encrypt_info.iteritems(): self.set_net_prop(entry_key, noneToString(entry_info[0]. get_edit_text())) elif not self.encryption_chkbox.get_state() and \ wireless.GetWirelessProperty(self.networkid, "encryption"): # Encrypt checkbox is off, but the network needs it. error(self.ui, self.parent, _('This network requires encryption to be enabled.')) return False else: self.set_net_prop("enctype", "None") AdvancedSettingsDialog.save_settings(self) # Save the autoconnect setting. This is not where it originally was # in the GTK UI. self.set_net_prop("automatic",self.autoconnect_chkbox.get_state()) if self.global_settings_chkbox.get_state(): self.set_net_prop('use_settings_globally', True) else: self.set_net_prop('use_settings_globally', False) wireless.RemoveGlobalEssidEntry(self.networkid) wireless.SaveWirelessNetworkProfile(self.networkid) return True