From 70066a688db2fd0249e229666dedfcd92d559fa3 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer <reinhold@kainhofer.com> Date: Sat, 18 Feb 2012 23:20:28 +0100 Subject: [PATCH] appliance_setup: Fully implement 8888 and USB config, saving/loading config, hostname change --- appliance_setup/appliance_setup.py | 150 ++++------------------------- appliance_setup/configuration.py | 93 ++---------------- appliance_setup/device_types.py | 94 +++++++++++++++--- appliance_setup/user_interface.py | 43 +++++++-- 4 files changed, 145 insertions(+), 235 deletions(-) diff --git a/appliance_setup/appliance_setup.py b/appliance_setup/appliance_setup.py index 8915d97..a22441e 100755 --- a/appliance_setup/appliance_setup.py +++ b/appliance_setup/appliance_setup.py @@ -32,7 +32,6 @@ from user_interface import * from helpers import * from configuration import * -#use Data::Dumper; VERSION=0.01; print """\ appliance_setup.py - version %.2f @@ -42,11 +41,6 @@ License: GPL v2 or later """ % (VERSION); - -# The PC always identifies itself as XXXXXXXX. -#our $thisboxname = "XXXXXXXX"; - - def ask_device (ui): devices = []; for f in device_factories: @@ -74,7 +68,7 @@ def ask_device (ui): ############################################################################### -## INFRASTRUCTURE WIRELESS SETUP (i.e. wlan through access point / router) +## WIRELESS SETUP (i.e. wlan through access point or ad-hoc) ############################################################################### @@ -86,85 +80,6 @@ def wifi_ask_ssid (ui, dev): if res: return (res, aps) -""" - -sub wifi_ask_security ($$) { - my $ap = shift; - my $aps = shift; - my %result = (); - my $sec = 0; - if (defined $aps->{$ap}) { - $sec = $aps->{$ap}->{'secmode'}; - $result{'channel'} = $aps->{$ap}->{'channel'}; - } - $sec = ask_choice ("Security: ", ["None", -1, "WEP", "WPA-PSK", "WPA2-PSK", "WPA/WPA2-PSK"], ['0', '1', '2', '4', '6'], $sec); - $result{'secmode'} = $sec; - - if ($sec == 0) { - # No encryption, nothing to ask the user - } elsif ($sec == 1) { - # WEP - progress "Using WEP security\n"; - $result{'authen'} = ask_choice ("Type of authentication:", ["Open System","Shared Key"], ['1','2'], '1'); - $result{'key'} = ask_wep_key ($ap); - $result{'key_len'} = length ($result{'key'})/2; - } elsif ($sec == 2 || $sec == 4 || $sec == 6 || $sec == 7) { - # WPA1 / WPA2 - progress "Using %s security\n", security2string($sec); - $result{'pskalset'} = ask_choice ("Type of encryption:", ["TKIP", "AES"], ['0','1'], '0'); - $result{'pskkey'} = ask_input ("Please enter the WPA passphrase for network '$ap': ", - \&is_wpa_passphrase, "\tEnter a passprase with 1-63 characters!\n"); - } else { - printf "ERROR: security type %s not supported\n", security2string($sec); - return wifi_ask_security ($ap, $aps); - } - return %result; -} - -sub wifi_config_create ($) { - my $newconfig = shift; - my $config = [ - ("4000", "IP_ADDR", $newconfig->{'ip_addr'}), # IP-address - ("4001", "GATEWAY", $newconfig->{'gateway'}), - ("4002", "MASK ", $newconfig->{'mask'}), - ("4020", "DHCP_MODE", $newconfig->{'dhcp'}), - ("4021", "", $newconfig->{'dhcp'}), # Unknown, == 4020 - ("4022", "", $newconfig->{'dhcp'}), # Unknown, == 4020 - ("5000", "", ""), # Unknown, always empty - ("5003", "", ""), # Unknown, always empty - ("5101", "", ""), # Unknown, always empty - ("5102", "", ""), # Unknown, always empty - ("5104", "", ""), # Unknown, always empty - ("5103", "", ""), # Unknown, always empty - ("7000", "SSID", $newconfig->{'SSID'}), - ("7001", "DOMAIN", ""), - ("7002", "CHANNEL", $newconfig->{'channel'}), - ("7003", "SECMODE", $newconfig->{'secmode'}), - ("7004", "KEY_LEN", $newconfig->{'key_len'}), - ("7005", "DEFAULTKEY","0"), - ("7006", "KEY0", $newconfig->{'key'}), - ("7007", "KEY1", ""), - ("7008", "KEY2", ""), - ("7009", "KEY3", ""), - ("7012", "AUTHEN", $newconfig->{'authen'}), - ("7013", "MODE", "0"), - ("7018", "PSKALSET", $newconfig->{'pskalset'}), - ("7019", "PSKKEY", $newconfig->{'pskkey'}), - ("7024", "STAMODE", "0"), - ("7025", "APCHANNEL", "5"), - ("7026", "CHMODE", "1"), - ("7030", "WLMODE", "0"), - ]; - return config_create ($config); -} - -""" - -############################################################################### -## AD-HOC WIRELESS SETUP (i.e. direct connection with print server and PC) -############################################################################### - - def adhoc_ask_ssid (ui, dev): ssid = "" @@ -179,42 +94,17 @@ def adhoc_ask_ssid (ui, dev): else: return ssid -""" -def adhoc_ask_channel (ap): - channel = False - while (!channel): - c = input ("Wireless channel for network '%s' [auto or 0-13]: " % ap); +def adhoc_ask_channel (ui, ssid): + channel = None + while (not channel): + c = ui.input ("Wireless channel for network '%s' [auto or 0-13]: " % ssid) if (c == "auto"): channel = "6" # FIXME elif (re.match ('^([0-9]|1[0-3])$', c)): channel = c - debug ("\tNew channel: %s\n" % channel) + ui.debug ("\tNew channel: %s\n" % channel) return channel -sub adhoc_config_create ($) { - my $newconfig = shift; - my $config = [ - ["7024", "STAMODE", "1"], - ["7025", "APCHANNEL", $newconfig->{'channel'}], - ["7026", "CHMODE", "1"], # FIXME: Shall we change this? - ["7030", "WLMODE", "1"], # FIXME: Shall we change this? - ["7100", "APSSID", $newconfig->{'SSID'}], - ["7103", "APSECMODE", $newconfig->{'secmode'}], - ["7104", "APKEY_LEN", $newconfig->{'key_len'}], - ["7105", "APDEFAULTKE","0"], - ["7106", "APKEY0", $newconfig->{'key'}], - ["7107", "APKEY1", ""], - ["7108", "APKEY2", ""], - ["7109", "APKEY3", ""], - ["7112", "APAUTHEN", $newconfig->{'authen'}], - ["7118", "APPSKALSET", $newconfig->{'pskalset'}], - ["7119", "APPSKKEY", $newconfig->{'pskkey'}] - ]; - return config_create ($config); -} - -""" - ############################################################################### ## MAIN OPERATIONS: ASK FOR OPERATION AND HANDLE IT ############################################################################### @@ -269,30 +159,26 @@ def main (): UI.debug ("\tSelected operation: %s\n" % operation) if (operation == "wifi_infrastructure"): ## Infrastructure, scan for APs - (newap, aps) = wifi_ask_ssid (UI, dev) - newconfig = {'SSID': newap) - UI.debug ("\tSelected wireless network: %s" % newap) - security = UI.wifi_ask_security ()#TODO: $newap, $aps); + (ssid, aps) = wifi_ask_ssid (UI, dev) + newconfig = {'SSID': ssid, 'wifi-type': 'infrastructure'} + UI.debug ("\tSelected wireless network: %s" % ssid) + security = UI.wifi_ask_security (ssid, aps.get (ssid)) newconfig.update (security) if (dev.capabilities['ip-address']): ip = UI.ask_IP_setting () newconfig.update (ip) - # TODO: - #my $newcfg = wifi_config_create (\%newconfig); - #device_config_send ($dev, $newcfg); + newcfg = dev.config_create (newconfig) + dev.config_send (newcfg) reconfigured = True elif (operation == "wifi_adhoc"): ## Ad-hoc connection to print server - # TODO - adhocssid = adhoc_ask_ssid (UI, dev) + ssid = adhoc_ask_ssid (UI, dev) dev.command_send ("9971:\n") - #my $channel = adhoc_ask_channel ($dev, $adhocssid); - #my %newconfig = ('SSID' => $adhocssid, - #'channel' => $channel, - #adhoc_ask_security ($adhocssid) - #); - #my $newcfg = adhoc_config_create (\%newconfig); - #device_config_send ($dev, $newcfg); + channel = adhoc_ask_channel (UI, ssid) + newconfig = {'SSID': ssid, 'channel': channel, 'wifi-type': 'ad-hoc'} + newconfig.update (UI.wifi_ask_security (ssid, None)); + newcfg = dev.config_create (newconfig) + dev.config_send (newcfg) reconfigured = True elif (operation == "change_hostname"): hostname = UI.ask_input ("New hostname: ", is_hostname, diff --git a/appliance_setup/configuration.py b/appliance_setup/configuration.py index 6505a99..401ff88 100644 --- a/appliance_setup/configuration.py +++ b/appliance_setup/configuration.py @@ -32,6 +32,8 @@ class Config: def set_config (self, cfg): self.cfgdata = cfg + def add_config (self, cfg): + self.cfgdata.extend (cfg) def print_configuration (self, text): res = text + "\tDevice name:\t%s\n" % self.val('0001') @@ -41,12 +43,12 @@ class Config: sec = self.val('7103'); res += "\tWireless mode:\tAd-hoc network\n" res += "\tSSID:\t\t%s\n" % self.val('7100') - res += "\tChannel:\t%s\n" % self.val('7102') + res += "\tChannel:\t%s\n" % self.val('7025') res += "\tSecurity:\t%s\n" % security2string (sec) - if (sec == 0): + if (sec == '0'): # None => nothing to display pass - elif (sec == 1): + elif (sec == '1'): # WEP => Print passphrase res += "\tWEP Key:\t%s\n" % self.val('7106') else: @@ -59,10 +61,10 @@ class Config: res += "\tSSID:\t\t%s\n" % self.val('7000') res += "\tChannel:\t%s\n" % self.val('7002') res += "\tSecurity:\t%s\n" % security2string (sec) - if (sec == 0): + if (sec == '0'): # None => nothing to display pass - elif (sec == 1): + elif (sec == '1'): # WEP => Print passphrase res += "\tAuthentication:\t%s\n" % authentication2string(self.val('7012')) res += "\tWEP Key:\t%s\n" % self.val('7006') @@ -105,12 +107,12 @@ class Config: else: print "Config line not in correct format:\n\t%s" % l - def to_string (self, cfg=None): + def to_string (self, cfg=None, verbose=True): res = "" if (not cfg): cfg = self.cfgdata for (l, key, value) in cfg: - res += "%s %s:%s\n" % (l, key, value) + res += "%s %s:%s\n" % (l, key if verbose else "", value) return res def save (self, filename): @@ -137,80 +139,3 @@ class Config: def remove_readonly (self): self.cfgdata = filter (lambda d: d[0] not in self.readonly, self.cfgdata) - - - -""" - - -############################################################################### -## INFRASTRUCTURE WIRELESS SETUP (i.e. wlan through access point / router) -############################################################################### - - -sub wifi_config_create ($) { - my $newconfig = shift; - my $config = [ - ["4000", "IP_ADDR", $newconfig->{'ip_addr'}], # IP-address - ["4001", "GATEWAY", $newconfig->{'gateway'}], - ["4002", "MASK ", $newconfig->{'mask'}], - ["4020", "DHCP_MODE", $newconfig->{'dhcp'}], - ["4021", "", $newconfig->{'dhcp'}], # Unknown, == 4020 - ["4022", "", $newconfig->{'dhcp'}], # Unknown, == 4020 - ["5000", "", ""], # Unknown, always empty - ["5003", "", ""], # Unknown, always empty - ["5101", "", ""], # Unknown, always empty - ["5102", "", ""], # Unknown, always empty - ["5104", "", ""], # Unknown, always empty - ["5103", "", ""], # Unknown, always empty - ["7000", "SSID", $newconfig->{'SSID'}], - ["7001", "DOMAIN", ""], - ["7002", "CHANNEL", $newconfig->{'channel'}], - ["7003", "SECMODE", $newconfig->{'secmode'}], - ["7004", "KEY_LEN", $newconfig->{'key_len'}], - ["7005", "DEFAULTKEY","0"], - ["7006", "KEY0", $newconfig->{'key'}], - ["7007", "KEY1", ""], - ["7008", "KEY2", ""], - ["7009", "KEY3", ""], - ["7012", "AUTHEN", $newconfig->{'authen'}], - ["7013", "MODE", "0"], - ["7018", "PSKALSET", $newconfig->{'pskalset'}], - ["7019", "PSKKEY", $newconfig->{'pskkey'}], - ["7024", "STAMODE", "0"], - ["7025", "APCHANNEL", "5"], - ["7026", "CHMODE", "1"], - ["7030", "WLMODE", "0"], - ]; - return config_create ($config); -} - - - -############################################################################### -## AD-HOC WIRELESS SETUP (i.e. direct connection with print server and PC) -############################################################################### - -sub adhoc_config_create ($) { - my $newconfig = shift; - my $config = [ - ["7024", "STAMODE", "1"], - ["7025", "APCHANNEL", $newconfig->{'channel'}], - ["7026", "CHMODE", "1"], # FIXME: Shall we change this? - ["7030", "WLMODE", "1"], # FIXME: Shall we change this? - ["7100", "APSSID", $newconfig->{'SSID'}], - ["7103", "APSECMODE", $newconfig->{'secmode'}], - ["7104", "APKEY_LEN", $newconfig->{'key_len'}], - ["7105", "APDEFAULTKE","0"], - ["7106", "APKEY0", $newconfig->{'key'}], - ["7107", "APKEY1", ""], - ["7108", "APKEY2", ""], - ["7109", "APKEY3", ""], - ["7112", "APAUTHEN", $newconfig->{'authen'}], - ["7118", "APPSKALSET", $newconfig->{'pskalset'}], - ["7119", "APPSKKEY", $newconfig->{'pskkey'}] - ]; - return config_create ($config); -} - -""" \ No newline at end of file diff --git a/appliance_setup/device_types.py b/appliance_setup/device_types.py index 91051bd..7045a7c 100755 --- a/appliance_setup/device_types.py +++ b/appliance_setup/device_types.py @@ -32,9 +32,6 @@ class Device: def device_string (self): pass - def detect_devices (self): - pass - def device_open (self): pass def device_close (self): @@ -88,11 +85,81 @@ class Device: pass def error (self, msg): self.ui.error (msg) + def set_hostname (self, hostname): + hostname = hostname[:19] config = Config (self.ui, cfg=[('0001', 'BOX_NAME', hostname)]); self.ui.debug ("\tChanging hostname using config\n\t%s\n" % config.to_string ()) return self.config_send (config) + def config_create (self, newconfig): + cfg = Config (self.ui) + adhoc = (newconfig.get ('wifi-type') == "ad-hoc") + + if (self.capabilities['ip-address'] and not adhoc): + cfg.add_config ([ + ("4000", "IP_ADDR", newconfig.get ('ip_addr','')), # IP-address + ("4001", "GATEWAY", newconfig.get ('gateway','')), + ("4002", "MASK ", newconfig.get ('mask','')), + ("4020", "DHCP_MODE", newconfig.get ('dhcp','')), + ("4021", "", newconfig.get ('dhcp','')), # Unknown, == 4020 + ("4022", "", newconfig.get ('dhcp','')), # Unknown, == 4020 + ]) + + ## Clear all SMB settings: + cfg.add_config ([ + ("5000", "", ""), # Unknown, always empty + ("5003", "", ""), # Unknown, always empty + ("5101", "", ""), # Unknown, always empty + ("5102", "", ""), # Unknown, always empty + ("5104", "", ""), # Unknown, always empty + ("5103", "", ""), # Unknown, always empty + ]) + + if (not adhoc): + cfg.add_config ([ + ("7000", "SSID", newconfig.get ('SSID','')), + ("7001", "DOMAIN", ""), + ("7002", "CHANNEL", newconfig.get ('channel','')), + ("7003", "SECMODE", newconfig.get ('secmode','')), + ("7004", "KEY_LEN", newconfig.get ('key_len','')), + ("7005", "DEFAULTKEY","0"), + ("7006", "KEY0", newconfig.get ('key','')), + ("7007", "KEY1", ""), + ("7008", "KEY2", ""), + ("7009", "KEY3", ""), + ("7012", "AUTHEN", newconfig.get ('authen','')), + ("7013", "MODE", "0"), + ("7018", "PSKALSET", newconfig.get ('pskalset','')), + ("7019", "PSKKEY", newconfig.get ('pskkey','')), + ("7024", "STAMODE", "0"), + ("7025", "APCHANNEL", "5"), + ("7026", "CHMODE", "1"), + ("7030", "WLMODE", "0"), + ]) + else: + cfg.add_config ([ + ("7024", "STAMODE", "1"), + ("7025", "APCHANNEL", newconfig.get ('channel','')), + ("7026", "CHMODE", "1"), # FIXME: Shall we change this? + ("7030", "WLMODE", "1"), # FIXME: Shall we change this? + ("7100", "APSSID", newconfig.get ('SSID','')), + ("7103", "APSECMODE", newconfig.get ('secmode','')), + ("7104", "APKEY_LEN", newconfig.get ('key_len','')), + ("7105", "APDEFAULTKE","0"), + ("7106", "APKEY0", newconfig.get ('key','')), + ("7107", "APKEY1", ""), + ("7108", "APKEY2", ""), + ("7109", "APKEY3", ""), + ("7112", "APAUTHEN", newconfig.get ('authen','')), + ("7118", "APPSKALSET", newconfig.get ('pskalset','')), + ("7119", "APPSKKEY", newconfig.get ('pskkey','')) + ]) + #print cfg + #print cfg.to_string (verbose=False) + return cfg + + class USBDeviceFactory (DeviceFactory): supported_devices = ( @@ -170,7 +237,8 @@ class USBDevice (Device): def device_reset (self): self.ui.progress ("Resetting the device, please wait") res = self.command_send ("9002:\n") - self.ui.debug ("\tSent 9002 reset command: %s (len: %s)" % (res, len(res))) + if res: + self.ui.debug ("\tSent 9002 reset command: %s (len: %s)" % (res, len(res))) # Poll the device until it doesn't respond. Then sleep for ~15 seconds try: i=0 @@ -288,8 +356,8 @@ class Ether8888Packet: class Ether8888DeviceFactory (DeviceFactory): supported_devices = ( - {'id': '\x04\xE0\x54\x00', 'desc':"Vonets VAP11G wireless bridge"}, - #{'id': '\x59\x4a\x34\x8c', 'desc':"HP2101nw Wireless USB print server (via WLAN)"}, + {'id': '\x04\xE0\x54\x00', 'desc':"Vonets VAP11G wireless bridge", 'supported': True}, + {'id': '\x59\x4a\x34\x8c', 'desc':"HP2101nw Wireless USB print server (via WLAN)", 'supported': False}, ); proto=0x8888; def __init__ (self): @@ -298,7 +366,8 @@ class Ether8888DeviceFactory (DeviceFactory): def list_supported (self): devices = []; for d in self.supported_devices: - devices.append ("%(desc)s, Ethernet, type 0x%(proto)04x" % dict({'proto': self.proto}, **d)); + if d.get('supported'): + devices.append ("%(desc)s, Ethernet, type 0x%(proto)04x" % dict({'proto': self.proto}, **d)); return devices; def detect (self, ui): @@ -335,16 +404,17 @@ class Ether8888DeviceFactory (DeviceFactory): if (not pack.decode (rxFrame)): ui.error ("decoding response packet of device detection") continue - is_broadcast = (pack.srcAddr == bcAddr) and (pack.dstAddr == bcAddr) + is_broadcast = (pack.srcAddr == bcAddr) or (pack.dstAddr == bcAddr) if is_broadcast: ui.debug ("Received broadcast package instead of response:") ui.hex_print (rxFrame) continue ifName,ifProto,pktType,hwType,hwAddr = sock.getsockname() devdesc = None + dev = None for d in self.supported_devices: if d['id'] == pack.data[2:6]: - devdesc = d['desc'] + dev = d break else: ui.hex_print (pack.srcAddr) @@ -352,7 +422,10 @@ class Ether8888DeviceFactory (DeviceFactory): continue ui.debug ("Received response packet:") ui.hex_print (rxFrame) - devices.append (Ether8888Device (ui, ifName, ifProto, pack.srcAddr, devdesc, localAddr = pack.dstAddr)); + if dev.get ('supported'): + devices.append (Ether8888Device (ui, ifName, ifProto, pack.srcAddr, dev.get('desc', "Unknown device"), localAddr = pack.dstAddr)) + else: + ui.progress ("Device {} (MAC {}, interface {}) not supported, ignoring response".format (dev.get('desc'), formatMAC (pack.srcAddr), ifName)) for s in sockets: s.close (); @@ -486,7 +559,6 @@ class Ether8888Device (Device): time.sleep (1) return self.raw_read (length, timeout) - def command_send (self, cfg): res = self.data_write (cfg, len(cfg), cmd=self.cmds.get('send_data'), unknown="\1\0") return self.data_read (25600) diff --git a/appliance_setup/user_interface.py b/appliance_setup/user_interface.py index 71fce11..76fc903 100755 --- a/appliance_setup/user_interface.py +++ b/appliance_setup/user_interface.py @@ -55,14 +55,14 @@ class UserInterface: def ask_IP_setting (self): dhcp = self.ask_choice ("IP-address assignment:", ["DHCP", "Manual"], ["Enable", "Disable"], "Enable"); result = {"dhcp": dhcp} - if (dhcp == "Enable"); - result['ip_addr'] = self.ask_ip_address ("IP-address of the device:") - result['mask'] = self.ask_ip_address ("Netmask:") - result['gateway'] = self.ask_ip_address ("IP-address of the gateway:") - else: + if (dhcp == "Enable"): result['ip_addr'] = "0.0.0.0" result['mask'] = "0.0.0.0" result['gateway'] = "0.0.0.0" + else: + result['ip_addr'] = self.ask_ip_address ("\tIP-address of the device:\t") + result['mask'] = self.ask_ip_address ("\tNetmask:\t\t\t") + result['gateway'] = self.ask_ip_address ("\tIP-address of the gateway:\t") return result def ask_operation (self): @@ -75,6 +75,33 @@ class UserInterface: pass def wait_enter (self, text): pass + # Request the type of security and if needed the required credentials + def wifi_ask_security (self,ssid, apsettings): + result = {} + if apsettings: + result['channel'] = apsettings.get ('channel') + result['secmode'] = apsettings.get ('secmode') + result['secmode'] = self.ask_choice ("Security: ", ["None", -1, "WEP", "WPA-PSK", "WPA2-PSK", "WPA/WPA2-PSK"], ['0', '1', '2', '4', '6'], result.get ('secmode')) + + if (result['secmode'] == '0'): + pass + elif (result['secmode'] == '1'): + # WEP + self.progress ("Using WEP security") + result['authen'] = self.ask_choice ("Type of authentication:", ["Open System","Shared Key"], ['1','2'], '1') + result['key'] = self.ask_wep_key (ssid) + result['key_len'] = len (result['key'])/2 + elif (result['secmode'] in ['2','4','6','7']): + # WPA1 / WPA2 + self.progress ("Using %s security" % security2string(result['secmode'])) + result['pskalset'] = self.ask_choice ("Type of encryption:", ["TKIP", "AES"], ['0','1'], '0') + result['pskkey'] = self.ask_input ("Please enter the WPA passphrase for network '%s': " % ssid, + is_wpa_passphrase, "\tEnter a passprase with 1-63 characters!") + else: + self.error ("security type %s not supported" % security2string(result['secmode'])) + return self.wifi_ask_security (ssid, apsettings) + return result + class ConsoleInterface (UserInterface): def __init__ (self, debug): @@ -174,12 +201,12 @@ class ConsoleInterface (UserInterface): pass def ask_ip_address (self, string): - return self.ask_input (string, self.is_ip_address, "\tInvalid input %s. Please enter a string of the form xxx.xxx.xxx.xxx, where each xxx is a number from 0 to 255.\n") + return self.ask_input (string, is_ip_address, "\tInvalid input %s. Please enter a string of the form xxx.xxx.xxx.xxx, where each xxx is a number from 0 to 255.\n") def ask_wep_key (self, ap): return self.ask_input ( "Please enter the WEP key (10 or 26 characters, 0-9 and a-f) for network '%s': " % ap, - helpers.is_wep_key, + is_wep_key, "\tInvalid key %s. Length can only be 10 or 26, use only digits 0-9 and letters a-f.\n\n") def wait_enter (self, text): @@ -230,7 +257,7 @@ class ConsoleInterface (UserInterface): try: i = int(newssid) print "int %s = %d" % (newssid,i) - if (i>0 and i<len(ssids)): + if (i>0 and i<=len(ssids)): print "In range" return ssids[i-1] else: -- GitLab