networkbrowser: migrate to iNetworkInfo (needs some testing)
[enigma2-plugins.git] / networkbrowser / src / NetworkBrowser.py
1 # -*- coding: utf-8 -*-
2 # for localized messages
3 #from __init__ import _
4 from enigma import eTimer
5 from Screens.Screen import Screen
6 from Screens.MessageBox import MessageBox
7 from Components.ActionMap import ActionMap
8 from Components.Sources.List import List
9 from Components.Sources.StaticText import StaticText
10 from Components.Network import iNetworkInfo
11 from Components.config import getConfigListEntry, ConfigIP
12 from Components.ConfigList import ConfigListScreen
13 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
14 from Tools.LoadPixmap import LoadPixmap
15 from cPickle import dump, load
16 from os import path as os_path, stat, mkdir, remove
17 from time import time
18 from stat import ST_MTIME
19
20 import netscan
21 from MountManager import AutoMountManager
22 from AutoMount import iAutoMount
23 from MountEdit import AutoMountEdit
24 from UserDialog import UserDialog
25
26 def write_cache(cache_file, cache_data):
27         #Does a cPickle dump
28         if not os_path.isdir( os_path.dirname(cache_file) ):
29                 try:
30                         mkdir( os_path.dirname(cache_file) )
31                 except OSError:
32                         print os_path.dirname(cache_file), '[Networkbrowser] is a file'
33         fd = open(cache_file, 'w')
34         dump(cache_data, fd, -1)
35         fd.close()
36
37 def valid_cache(cache_file, cache_ttl):
38         #See if the cache file exists and is still living
39         try:
40                 mtime = stat(cache_file)[ST_MTIME]
41         except:
42                 return 0
43         curr_time = time()
44         if (curr_time - mtime) > cache_ttl:
45                 return 0
46         else:
47                 return 1
48
49 def load_cache(cache_file):
50         #Does a cPickle load
51         fd = open(cache_file)
52         cache_data = load(fd)
53         fd.close()
54         return cache_data
55
56 class NetworkDescriptor:
57         def __init__(self, name = "NetworkServer", description = ""):
58                 self.name = name
59                 self.description = description
60
61 class NetworkBrowser(Screen):
62         skin = """
63                 <screen name="NetworkBrowser" position="90,80" size="560,450" title="Network Neighbourhood">
64                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
65                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
66                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
67                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
68                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
69                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
70                         <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
71                         <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
72                         <widget source="list" render="Listbox" position="5,50" size="540,350" zPosition="10" scrollbarMode="showOnDemand">
73                                 <convert type="TemplatedMultiContent">
74                                         {"template": [
75                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 0), size = (48, 48), png = 1), # index 1 is the expandable/expanded/verticalline icon
76                                                         MultiContentEntryText(pos = (50, 4), size = (420, 26), font=2, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the Hostname
77                                                         MultiContentEntryText(pos = (140, 5), size = (320, 25), font=0, flags = RT_HALIGN_LEFT, text = 3), # index 3 is the sharename
78                                                         MultiContentEntryText(pos = (140, 26), size = (320, 17), font=1, flags = RT_HALIGN_LEFT, text = 4), # index 4 is the sharedescription
79                                                         MultiContentEntryPixmapAlphaTest(pos = (45, 0), size = (48, 48), png = 5), # index 5 is the nfs/cifs icon
80                                                         MultiContentEntryPixmapAlphaTest(pos = (90, 0), size = (48, 48), png = 6), # index 6 is the isMounted icon
81                                                 ],
82                                         "fonts": [gFont("Regular", 20),gFont("Regular", 14),gFont("Regular", 24)],
83                                         "itemHeight": 50
84                                         }
85                                 </convert>
86                         </widget>
87                         <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="1" size="560,2" />         
88                         <widget source="infotext" render="Label" position="0,420" size="560,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
89                 </screen>"""
90
91         def __init__(self, session, iface,plugin_path):
92                 Screen.__init__(self, session)
93                 self.skin_path = plugin_path
94                 self.session = session
95                 self.iface = iface
96                 if self.iface is None:
97                         self.iface = 'eth0'
98                 self.networklist = None
99                 self.device = None
100                 self.mounts = None
101                 self.expanded = []
102                 self.cache_ttl = 604800 #Seconds cache is considered valid, 7 Days should be ok
103                 self.cache_file = '/etc/enigma2/networkbrowser.cache' #Path to cache directory
104
105                 self["key_red"] = StaticText(_("Close"))
106                 self["key_green"] = StaticText(_("Mounts management"))
107                 self["key_yellow"] = StaticText(_("Rescan"))
108                 self["key_blue"] = StaticText(_("Expert"))
109                 self["infotext"] = StaticText(_("Press OK to mount!"))
110                 
111                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
112                 {
113                         "ok": self.go,
114                         "back": self.close,
115                         "red": self.close,
116                         "green": self.keyGreen,
117                         "yellow": self.keyYellow,
118                         "blue": self.keyBlue,
119                 })
120
121                 self.list = []
122                 self.statuslist = []
123                 self.listindex = 0
124                 self["list"] = List(self.list)
125                 self["list"].onSelectionChanged.append(self.selectionChanged)
126
127                 self.onLayoutFinish.append(self.startRun)
128                 self.onShown.append(self.setWindowTitle)
129                 self.onClose.append(self.cleanup)
130                 self.Timer = eTimer()
131                 self.Timer_conn = self.Timer.timeout.connect(self.TimerFire)
132
133         def cleanup(self):
134                 del self.Timer
135                 iAutoMount.stopMountConsole()
136
137         def startRun(self):
138                 self.expanded = []
139                 self.setStatus('update')
140                 self.mounts = iAutoMount.getMountsList()
141                 self["infotext"].setText("")
142                 self.vc = valid_cache(self.cache_file, self.cache_ttl)
143                 if self.cache_ttl > 0 and self.vc != 0:
144                         self.process_NetworkIPs()
145                 else:
146                         self.Timer.start(3000)
147
148         def TimerFire(self):
149                 self.Timer.stop()
150                 self.process_NetworkIPs()
151
152         def setWindowTitle(self):
153                 self.setTitle(_("Browse network neighbourhood"))
154
155         def keyGreen(self):
156                 self.session.open(AutoMountManager, None, self.skin_path)
157
158         def keyYellow(self):
159                 if (os_path.exists(self.cache_file) == True):
160                         remove(self.cache_file)
161                 self.startRun()
162
163         def keyBlue(self):
164                 self.session.openWithCallback(self.scanIPclosed,ScanIP)
165
166         def scanIPclosed(self,result):
167                 if result[0]:
168                         if result[1] == "address":
169                                 print "[Networkbrowser] got IP:",result[1]
170                                 nwlist = []
171                                 nwlist.append(netscan.netzInfo(result[0] + "/24"))
172                                 self.networklist += nwlist[0]
173                         elif result[1] == "nfs":
174                                 self.networklist.append(['host', result[0], result[0] , '00:00:00:00:00:00', result[0], 'Master Browser'])
175
176                 if len(self.networklist) > 0:
177                         write_cache(self.cache_file, self.networklist)
178                         self.updateHostsList()
179
180         def setStatus(self,status = None):
181                 if status:
182                         self.statuslist = []
183                         if status == 'update':
184                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/update.png"))
185                                 self.statuslist.append(( ['info'], statuspng, _("Searching your network. Please wait..."), None, None, None, None ))
186                                 self['list'].setList(self.statuslist)
187                         elif status == 'error':
188                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/error.png"))
189                                 self.statuslist.append(( ['info'], statuspng, _("No network devices found!"), None, None, None, None ))
190                                 self['list'].setList(self.statuslist)
191
192         def process_NetworkIPs(self):
193                 self.inv_cache = 0
194                 self.vc = valid_cache(self.cache_file, self.cache_ttl)
195                 if self.cache_ttl > 0 and self.vc != 0:
196                         print '[Networkbrowser] Loading network cache from ',self.cache_file
197                         try:
198                                 self.networklist = load_cache(self.cache_file)
199                         except:
200                                 self.inv_cache = 1
201                 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
202                         print '[Networkbrowser] Getting fresh network list'
203                         self.networklist = self.getNetworkIPs()
204                         write_cache(self.cache_file, self.networklist)
205                 if len(self.networklist) > 0:
206                         self.updateHostsList()
207                 else:
208                         self.setStatus('error')
209
210         def getNetworkIPs(self):
211                 nwlist = []
212                 sharelist = []
213                 self.IP = iNetworkInfo.getConfiguredInterfaces()[self.iface].ipv4.address
214                 if len(self.IP):
215                         strIP = str(self.IP[0]) + "." + str(self.IP[1]) + "." + str(self.IP[2]) + ".0/24"
216                         nwlist.append(netscan.netzInfo(strIP))
217                 tmplist = nwlist[0]
218                 return tmplist
219
220         def getNetworkShares(self,hostip,hostname,devicetype):
221                 sharelist = []
222                 self.sharecache_file = None
223                 self.sharecache_file = '/etc/enigma2/' + hostname.strip() + '.cache' #Path to cache directory
224                 if os_path.exists(self.sharecache_file):
225                         print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
226                         try:
227                                 self.hostdata = load_cache(self.sharecache_file)
228                                 username = self.hostdata['username']
229                                 password = self.hostdata['password']
230                         except:
231                                 username = "username"
232                                 password = "password"
233                 else:
234                         username = "username"
235                         password = "password"
236
237                 if devicetype == 'unix':
238                         smblist=netscan.smbShare(hostip,hostname,username,password)
239                         for x in smblist:
240                                 if len(x) == 6:
241                                         if x[3] != 'IPC$':
242                                                 sharelist.append(x)
243                         nfslist=netscan.nfsShare(hostip,hostname)
244                         for x in nfslist:
245                                 if len(x) == 6:
246                                         sharelist.append(x)
247                 else:
248                         smblist=netscan.smbShare(hostip,hostname,username,password)
249                         for x in smblist:
250                                 if len(x) == 6:
251                                         if x[3] != 'IPC$':
252                                                 sharelist.append(x)
253                 return sharelist
254
255         def updateHostsList(self):
256                 self.list = []
257                 self.network = {}
258                 for x in self.networklist:
259                         if not self.network.has_key(x[2]):
260                                 self.network[x[2]] = []
261                         self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
262                 
263                 for x in self.network.keys():
264                         hostentry = self.network[x][0][1]
265                         name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
266                         expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
267                         self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
268
269                 if len(self.list):
270                         for entry in self.list:
271                                 entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
272                         self.list.sort(key=lambda x: x[0][2])
273                         for entry in self.list:
274                                 entry[0][2]= entry[0][2].replace(" ", "")
275                 self["list"].setList(self.list)
276                 self["list"].setIndex(self.listindex)
277
278         def updateNetworkList(self):
279                 self.list = []
280                 self.network = {}
281                 self.mounts = iAutoMount.getMountsList() # reloading mount list
282                 for x in self.networklist:
283                         if not self.network.has_key(x[2]):
284                                 self.network[x[2]] = []
285                         self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
286                 self.network.keys().sort()
287                 for x in self.network.keys():
288                         if self.network[x][0][1][3] == '00:00:00:00:00:00':
289                                 self.device = 'unix'
290                         else:
291                                 self.device = 'windows'
292                         if x in self.expanded:
293                                 networkshares = self.getNetworkShares(x,self.network[x][0][1][1].strip(),self.device)
294                                 hostentry = self.network[x][0][1]
295                                 name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
296                                 expandedIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
297                                 self.list.append(( hostentry, expandedIcon, name, None, None, None, None ))
298                                 for share in networkshares:
299                                         self.list.append(self.BuildNetworkShareEntry(share))
300                         else: # HOSTLIST - VIEW
301                                 hostentry = self.network[x][0][1]
302                                 name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
303                                 expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
304                                 self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
305                 if len(self.list):
306                         for entry in self.list:
307                                 entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
308                         self.list.sort(key=lambda x: x[0][2])
309                         for entry in self.list:
310                                 entry[0][2]= entry[0][2].replace(" ", "")
311                 self["list"].setList(self.list)
312                 self["list"].setIndex(self.listindex)
313
314         def BuildNetworkShareEntry(self,share):
315                 verticallineIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/verticalLine.png"))
316                 sharetype = share[0]
317                 localsharename = share[1]
318                 sharehost = share[2]
319
320                 if sharetype == 'smbShare':
321                         sharedir = share[3]
322                         sharedescription = share[5]
323                 else:
324                         sharedir = share[4]
325                         sharedescription = share[3]
326
327                 if sharetype == 'nfsShare':
328                         newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-nfs.png"))
329                 else:
330                         newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-smb.png"))
331
332                 self.isMounted = False
333                 for sharename, sharedata in self.mounts.items():
334                         if sharedata['ip'] == sharehost:
335                                 if sharetype == 'nfsShare' and sharedata['mounttype'] == 'nfs':
336                                         if sharedir == sharedata['sharedir']:
337                                                 if sharedata["isMounted"] is True:
338                                                         self.isMounted = True
339                                 if sharetype == 'smbShare' and sharedata['mounttype'] == 'cifs':
340                                         if sharedir == sharedata['sharedir']:
341                                                 if sharedata["isMounted"] is True:
342                                                         self.isMounted = True
343                 if self.isMounted is True:
344                         isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/ok.png"))
345                 else:
346                         isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/cancel.png"))
347
348                 return((share, verticallineIcon, None, sharedir, sharedescription, newpng, isMountedpng))
349
350         def selectionChanged(self):
351                 current = self["list"].getCurrent()
352                 self.listindex = self["list"].getIndex()
353                 if current:
354                         if len(current[0]) >= 2:
355                                 if current[0][0] in ("nfsShare", "smbShare"):
356                                         self["infotext"].setText(_("Press OK to mount this share!"))
357                                 else:
358                                         selectedhost = current[0][2]
359                                         if selectedhost in self.expanded:
360                                                 self["infotext"].setText(_("Press OK to collapse this host"))
361                                         else:
362                                                 self["infotext"].setText(_("Press OK to expand this host"))
363
364         def go(self):
365                 sel = self["list"].getCurrent()
366                 if sel is None:
367                         return
368                 if len(sel[0]) <= 1:
369                         return
370                 selectedhost = sel[0][2]
371                 selectedhostname = sel[0][1]
372
373                 self.hostcache_file = None
374                 if sel[0][0] == 'host': # host entry selected
375                         if selectedhost in self.expanded:
376                                 self.expanded.remove(selectedhost)
377                                 self.updateNetworkList()
378                         else:
379                                 self.hostcache_file = None
380                                 self.hostcache_file = '/etc/enigma2/' + selectedhostname.strip() + '.cache' #Path to cache directory
381                                 if os_path.exists(self.hostcache_file):
382                                         print '[Networkbrowser] Loading userinfo cache from ',self.hostcache_file
383                                         try:
384                                                 self.hostdata = load_cache(self.hostcache_file)
385                                                 self.passwordQuestion(False)
386                                         except:
387                                                 self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
388                                 else:
389                                         self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
390
391                 if sel[0][0] == 'nfsShare': # share entry selected
392                         print '[Networkbrowser] sel nfsShare'
393                         self.openMountEdit(sel[0])
394                 if sel[0][0] == 'smbShare': # share entry selected
395                         print '[Networkbrowser] sel cifsShare'
396                         self.hostcache_file = None
397                         self.hostcache_file = '/etc/enigma2/' + selectedhostname.strip() + '.cache' #Path to cache directory
398                         if os_path.exists(self.hostcache_file):
399                                 print '[Networkbrowser] userinfo found from ',self.sharecache_file
400                                 self.openMountEdit(sel[0])
401                         else:
402                                 self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
403
404         def passwordQuestion(self, ret = False):
405                 sel = self["list"].getCurrent()
406                 selectedhost = sel[0][2]
407                 selectedhostname = sel[0][1]
408                 if (ret == True):
409                         self.session.openWithCallback(self.UserDialogClosed, UserDialog, self.skin_path, selectedhostname.strip())
410                 else:
411                         if sel[0][0] == 'host': # host entry selected
412                                 if selectedhost in self.expanded:
413                                         self.expanded.remove(selectedhost)
414                                 else:
415                                         self.expanded.append(selectedhost)
416                                 self.updateNetworkList()
417                         if sel[0][0] == 'nfsShare': # share entry selected
418                                 self.openMountEdit(sel[0])
419                         if sel[0][0] == 'smbShare': # share entry selected
420                                 self.openMountEdit(sel[0])
421
422         def UserDialogClosed(self, *ret):
423                 if ret is not None and len(ret):
424                         self.go()
425
426         def openMountEdit(self, selection):
427                 if selection is not None and len(selection):
428                         mounts = iAutoMount.getMountsList()
429                         if selection[0] == 'nfsShare': # share entry selected
430                                 #Initialize blank mount enty
431                                 data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
432                                 # add data
433                                 data['mounttype'] = 'nfs'
434                                 data['active'] = True
435                                 data['ip'] = selection[2]
436                                 data['sharename'] = selection[1]
437                                 data['sharedir'] = selection[4]
438                                 data['options'] = "rw,nolock,tcp"
439
440                                 for sharename, sharedata in mounts.items():
441                                         if sharedata['ip'] == selection[2] and sharedata['sharedir'] == selection[4]:
442                                                 data = sharedata
443                                 self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
444                         if selection[0] == 'smbShare': # share entry selected
445                                 #Initialize blank mount enty
446                                 data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
447                                 # add data
448                                 data['mounttype'] = 'cifs'
449                                 data['active'] = True
450                                 data['ip'] = selection[2]
451                                 data['sharename'] = selection[1]
452                                 data['sharedir'] = selection[3]
453                                 data['options'] = "rw"
454                                 self.sharecache_file = None
455                                 self.sharecache_file = '/etc/enigma2/' + selection[1].strip() + '.cache' #Path to cache directory
456                                 if os_path.exists(self.sharecache_file):
457                                         print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
458                                         try:
459                                                 self.hostdata = load_cache(self.sharecache_file)
460                                                 data['username'] = self.hostdata['username']
461                                                 data['password'] = self.hostdata['password']
462                                         except:
463                                                 data['username'] = "username"
464                                                 data['password'] = "password"
465                                 else:
466                                         data['username'] = "username"
467                                         data['password'] = "password"
468
469                                 for sharename, sharedata in mounts.items():
470                                         if sharedata['ip'] == selection[2].strip() and sharedata['sharedir'] == selection[3].strip():
471                                                 data = sharedata
472                                 self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
473
474         def MountEditClosed(self, returnValue = None):
475                 if returnValue == None:
476                         self.updateNetworkList()
477
478 class ScanIP(Screen, ConfigListScreen):
479         skin = """
480                 <screen name="ScanIP" position="center,center" size="560,80" title="Scan IP" >
481                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
482                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
483                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
484                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
485                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
486                         <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
487                         <widget name="config" position="5,50" size="540,25" scrollbarMode="showOnDemand" />
488                 </screen>"""
489
490         def __init__(self, session):
491                 Screen.__init__(self, session)
492                 self.session = session
493
494                 self["key_red"] = StaticText(_("Cancel"))
495                 self["key_green"] = StaticText(_("Scan NFS share"))
496                 self["key_yellow"] = StaticText(_("Scan range"))
497
498                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
499                 {
500                         "back": self.exit,
501                         "red": self.exit,
502                         "cancel": self.exit,
503                         "green": self.goNfs,
504                         "yellow": self.goAddress,
505                 }, -1)
506                 
507                 self.ipAddress = ConfigIP(default=[0,0,0,0])
508                 
509                 ConfigListScreen.__init__(self, [
510                         getConfigListEntry(_("IP Address"), self.ipAddress),
511                 ], self.session)
512
513                 self.onLayoutFinish.append(self.layoutFinished)
514
515         def exit(self):
516                 self.close((None,None))
517
518         def layoutFinished(self):
519                 self.setWindowTitle()
520
521         def setWindowTitle(self):
522                 self.setTitle(_("Enter IP to scan..."))
523
524         def goAddress(self):
525                 if self.ipAddress.getText() != "0.0.0.0":
526                         self.close((self.ipAddress.getText(), "address"))
527                 else:
528                         self.exit
529
530         def goNfs(self):
531                 if self.ipAddress.getText() != "0.0.0.0":
532                         self.close((self.ipAddress.getText(), "nfs"))
533                 else:
534                         self.exit
535