1 # -*- coding: utf-8 -*-
2 # for localized messages
3 #from __init__ import _
4 from enigma import eTimer, getDesktop
5 from Screens.Screen import Screen
6 from Screens.MessageBox import MessageBox
7 from Components.Label import Label
8 from Components.ActionMap import ActionMap, NumberActionMap
9 from Components.Sources.List import List
10 from Components.Sources.StaticText import StaticText
11 from Components.Network import iNetwork
12 from Components.Input import Input
13 from Components.config import getConfigListEntry, NoSave, config, ConfigIP
14 from Components.ConfigList import ConfigList, ConfigListScreen
15 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
16 from Tools.LoadPixmap import LoadPixmap
17 from cPickle import dump, load
18 from os import path as os_path, stat, mkdir, remove
20 from stat import ST_MTIME
23 from MountManager import AutoMountManager
24 from AutoMount import iAutoMount
25 from MountEdit import AutoMountEdit
26 from UserDialog import UserDialog
28 def write_cache(cache_file, cache_data):
30 if not os_path.isdir( os_path.dirname(cache_file) ):
32 mkdir( os_path.dirname(cache_file) )
34 print os_path.dirname(cache_file), '[Networkbrowser] is a file'
35 fd = open(cache_file, 'w')
36 dump(cache_data, fd, -1)
39 def valid_cache(cache_file, cache_ttl):
40 #See if the cache file exists and is still living
42 mtime = stat(cache_file)[ST_MTIME]
46 if (curr_time - mtime) > cache_ttl:
51 def load_cache(cache_file):
58 class NetworkDescriptor:
59 def __init__(self, name = "NetworkServer", description = ""):
61 self.description = description
63 class NetworkBrowser(Screen):
65 <screen name="NetworkBrowser" position="90,80" size="560,450" title="Network Neighbourhood">
66 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
67 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
68 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
69 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
70 <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" />
71 <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" />
72 <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" />
73 <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" />
74 <widget source="list" render="Listbox" position="5,50" size="540,350" zPosition="10" scrollbarMode="showOnDemand">
75 <convert type="TemplatedMultiContent">
77 MultiContentEntryPixmapAlphaTest(pos = (0, 0), size = (48, 48), png = 1), # index 1 is the expandable/expanded/verticalline icon
78 MultiContentEntryText(pos = (50, 4), size = (420, 26), font=2, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the Hostname
79 MultiContentEntryText(pos = (140, 5), size = (320, 25), font=0, flags = RT_HALIGN_LEFT, text = 3), # index 3 is the sharename
80 MultiContentEntryText(pos = (140, 26), size = (320, 17), font=1, flags = RT_HALIGN_LEFT, text = 4), # index 4 is the sharedescription
81 MultiContentEntryPixmapAlphaTest(pos = (45, 0), size = (48, 48), png = 5), # index 5 is the nfs/cifs icon
82 MultiContentEntryPixmapAlphaTest(pos = (90, 0), size = (48, 48), png = 6), # index 6 is the isMounted icon
84 "fonts": [gFont("Regular", 20),gFont("Regular", 14),gFont("Regular", 24)],
89 <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="1" size="560,2" />
90 <widget source="infotext" render="Label" position="0,420" size="560,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
93 def __init__(self, session, iface,plugin_path):
94 Screen.__init__(self, session)
95 self.skin_path = plugin_path
96 self.session = session
98 if self.iface is None:
100 self.networklist = None
104 self.cache_ttl = 604800 #Seconds cache is considered valid, 7 Days should be ok
105 self.cache_file = '/etc/enigma2/networkbrowser.cache' #Path to cache directory
107 self["key_red"] = StaticText(_("Close"))
108 self["key_green"] = StaticText(_("Mounts management"))
109 self["key_yellow"] = StaticText(_("Rescan"))
110 self["key_blue"] = StaticText(_("Expert"))
111 self["infotext"] = StaticText(_("Press OK to mount!"))
113 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
118 "green": self.keyGreen,
119 "yellow": self.keyYellow,
120 "blue": self.keyBlue,
126 self["list"] = List(self.list)
127 self["list"].onSelectionChanged.append(self.selectionChanged)
129 self.onLayoutFinish.append(self.startRun)
130 self.onShown.append(self.setWindowTitle)
131 self.onClose.append(self.cleanup)
132 self.Timer = eTimer()
133 self.Timer.callback.append(self.TimerFire)
137 iAutoMount.stopMountConsole()
138 iNetwork.stopRestartConsole()
139 iNetwork.stopGetInterfacesConsole()
143 self.setStatus('update')
144 self.mounts = iAutoMount.getMountsList()
145 self["infotext"].setText("")
146 self.vc = valid_cache(self.cache_file, self.cache_ttl)
147 if self.cache_ttl > 0 and self.vc != 0:
148 self.process_NetworkIPs()
150 self.Timer.start(3000)
154 self.process_NetworkIPs()
156 def setWindowTitle(self):
157 self.setTitle(_("Browse network neighbourhood"))
160 self.session.open(AutoMountManager, None, self.skin_path)
163 if (os_path.exists(self.cache_file) == True):
164 remove(self.cache_file)
168 self.session.openWithCallback(self.scanIPclosed,ScanIP)
170 def scanIPclosed(self,result):
172 if result[1] == "address":
173 print "[Networkbrowser] got IP:",result[1]
175 nwlist.append(netscan.netzInfo(result[0] + "/24"))
176 self.networklist += nwlist[0]
177 elif result[1] == "nfs":
178 self.networklist.append(['host', result[0], result[0] , '00:00:00:00:00:00', result[0], 'Master Browser'])
180 if len(self.networklist) > 0:
181 write_cache(self.cache_file, self.networklist)
182 self.updateHostsList()
184 def setStatus(self,status = None):
187 if status == 'update':
188 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/update.png"))
189 self.statuslist.append(( ['info'], statuspng, _("Searching your network. Please wait..."), None, None, None, None ))
190 self['list'].setList(self.statuslist)
191 elif status == 'error':
192 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/error.png"))
193 self.statuslist.append(( ['info'], statuspng, _("No network devices found!"), None, None, None, None ))
194 self['list'].setList(self.statuslist)
196 def process_NetworkIPs(self):
198 self.vc = valid_cache(self.cache_file, self.cache_ttl)
199 if self.cache_ttl > 0 and self.vc != 0:
200 print '[Networkbrowser] Loading network cache from ',self.cache_file
202 self.networklist = load_cache(self.cache_file)
205 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
206 print '[Networkbrowser] Getting fresh network list'
207 self.networklist = self.getNetworkIPs()
208 write_cache(self.cache_file, self.networklist)
209 if len(self.networklist) > 0:
210 self.updateHostsList()
212 self.setStatus('error')
214 def getNetworkIPs(self):
217 self.IP = iNetwork.getAdapterAttribute(self.iface, "ip")
219 strIP = str(self.IP[0]) + "." + str(self.IP[1]) + "." + str(self.IP[2]) + ".0/24"
220 nwlist.append(netscan.netzInfo(strIP))
224 def getNetworkShares(self,hostip,hostname,devicetype):
226 self.sharecache_file = None
227 self.sharecache_file = '/etc/enigma2/' + hostname.strip() + '.cache' #Path to cache directory
228 if os_path.exists(self.sharecache_file):
229 print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
231 self.hostdata = load_cache(self.sharecache_file)
232 username = self.hostdata['username']
233 password = self.hostdata['password']
235 username = "username"
236 password = "password"
238 username = "username"
239 password = "password"
241 if devicetype == 'unix':
242 smblist=netscan.smbShare(hostip,hostname,username,password)
247 nfslist=netscan.nfsShare(hostip,hostname)
252 smblist=netscan.smbShare(hostip,hostname,username,password)
259 def updateHostsList(self):
262 for x in self.networklist:
263 if not self.network.has_key(x[2]):
264 self.network[x[2]] = []
265 self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
267 for x in self.network.keys():
268 hostentry = self.network[x][0][1]
269 name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
270 expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
271 self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
274 for entry in self.list:
275 entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
276 self.list.sort(key=lambda x: x[0][2])
277 for entry in self.list:
278 entry[0][2]= entry[0][2].replace(" ", "")
279 self["list"].setList(self.list)
280 self["list"].setIndex(self.listindex)
282 def updateNetworkList(self):
285 self.mounts = iAutoMount.getMountsList() # reloading mount list
286 for x in self.networklist:
287 if not self.network.has_key(x[2]):
288 self.network[x[2]] = []
289 self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
290 self.network.keys().sort()
291 for x in self.network.keys():
292 if self.network[x][0][1][3] == '00:00:00:00:00:00':
295 self.device = 'windows'
296 if x in self.expanded:
297 networkshares = self.getNetworkShares(x,self.network[x][0][1][1].strip(),self.device)
298 hostentry = self.network[x][0][1]
299 name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
300 expandedIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
301 self.list.append(( hostentry, expandedIcon, name, None, None, None, None ))
302 for share in networkshares:
303 self.list.append(self.BuildNetworkShareEntry(share))
304 else: # HOSTLIST - VIEW
305 hostentry = self.network[x][0][1]
306 name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
307 expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
308 self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
310 for entry in self.list:
311 entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
312 self.list.sort(key=lambda x: x[0][2])
313 for entry in self.list:
314 entry[0][2]= entry[0][2].replace(" ", "")
315 self["list"].setList(self.list)
316 self["list"].setIndex(self.listindex)
318 def BuildNetworkShareEntry(self,share):
319 verticallineIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/verticalLine.png"))
321 localsharename = share[1]
324 if sharetype == 'smbShare':
326 sharedescription = share[5]
329 sharedescription = share[3]
331 if sharetype == 'nfsShare':
332 newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-nfs.png"))
334 newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-smb.png"))
336 self.isMounted = False
337 for sharename, sharedata in self.mounts.items():
338 if sharedata['ip'] == sharehost:
339 if sharetype == 'nfsShare' and sharedata['mounttype'] == 'nfs':
340 if sharedir == sharedata['sharedir']:
341 if sharedata["isMounted"] is True:
342 self.isMounted = True
343 if sharetype == 'smbShare' and sharedata['mounttype'] == 'cifs':
344 if sharedir == sharedata['sharedir']:
345 if sharedata["isMounted"] is True:
346 self.isMounted = True
347 if self.isMounted is True:
348 isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/ok.png"))
350 isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/cancel.png"))
352 return((share, verticallineIcon, None, sharedir, sharedescription, newpng, isMountedpng))
354 def selectionChanged(self):
355 current = self["list"].getCurrent()
356 self.listindex = self["list"].getIndex()
358 if len(current[0]) >= 2:
359 if current[0][0] in ("nfsShare", "smbShare"):
360 self["infotext"].setText(_("Press OK to mount this share!"))
362 selectedhost = current[0][2]
363 if selectedhost in self.expanded:
364 self["infotext"].setText(_("Press OK to collapse this host"))
366 self["infotext"].setText(_("Press OK to expand this host"))
369 sel = self["list"].getCurrent()
374 selectedhost = sel[0][2]
375 selectedhostname = sel[0][1]
377 self.hostcache_file = None
378 if sel[0][0] == 'host': # host entry selected
379 if selectedhost in self.expanded:
380 self.expanded.remove(selectedhost)
381 self.updateNetworkList()
383 self.hostcache_file = None
384 self.hostcache_file = '/etc/enigma2/' + selectedhostname.strip() + '.cache' #Path to cache directory
385 if os_path.exists(self.hostcache_file):
386 print '[Networkbrowser] Loading userinfo cache from ',self.hostcache_file
388 self.hostdata = load_cache(self.hostcache_file)
389 self.passwordQuestion(False)
391 self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
393 self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
395 if sel[0][0] == 'nfsShare': # share entry selected
396 print '[Networkbrowser] sel nfsShare'
397 self.openMountEdit(sel[0])
398 if sel[0][0] == 'smbShare': # share entry selected
399 print '[Networkbrowser] sel cifsShare'
400 self.hostcache_file = None
401 self.hostcache_file = '/etc/enigma2/' + selectedhostname.strip() + '.cache' #Path to cache directory
402 if os_path.exists(self.hostcache_file):
403 print '[Networkbrowser] userinfo found from ',self.sharecache_file
404 self.openMountEdit(sel[0])
406 self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
408 def passwordQuestion(self, ret = False):
409 sel = self["list"].getCurrent()
410 selectedhost = sel[0][2]
411 selectedhostname = sel[0][1]
413 self.session.openWithCallback(self.UserDialogClosed, UserDialog, self.skin_path, selectedhostname.strip())
415 if sel[0][0] == 'host': # host entry selected
416 if selectedhost in self.expanded:
417 self.expanded.remove(selectedhost)
419 self.expanded.append(selectedhost)
420 self.updateNetworkList()
421 if sel[0][0] == 'nfsShare': # share entry selected
422 self.openMountEdit(sel[0])
423 if sel[0][0] == 'smbShare': # share entry selected
424 self.openMountEdit(sel[0])
426 def UserDialogClosed(self, *ret):
427 if ret is not None and len(ret):
430 def openMountEdit(self, selection):
431 if selection is not None and len(selection):
432 mounts = iAutoMount.getMountsList()
433 if selection[0] == 'nfsShare': # share entry selected
434 #Initialize blank mount enty
435 data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
437 data['mounttype'] = 'nfs'
438 data['active'] = True
439 data['ip'] = selection[2]
440 data['sharename'] = selection[1]
441 data['sharedir'] = selection[4]
442 data['options'] = "rw,nolock,tcp"
444 for sharename, sharedata in mounts.items():
445 if sharedata['ip'] == selection[2] and sharedata['sharedir'] == selection[4]:
447 self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
448 if selection[0] == 'smbShare': # share entry selected
449 #Initialize blank mount enty
450 data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
452 data['mounttype'] = 'cifs'
453 data['active'] = True
454 data['ip'] = selection[2]
455 data['sharename'] = selection[1]
456 data['sharedir'] = selection[3]
457 data['options'] = "rw"
458 self.sharecache_file = None
459 self.sharecache_file = '/etc/enigma2/' + selection[1].strip() + '.cache' #Path to cache directory
460 if os_path.exists(self.sharecache_file):
461 print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
463 self.hostdata = load_cache(self.sharecache_file)
464 data['username'] = self.hostdata['username']
465 data['password'] = self.hostdata['password']
467 data['username'] = "username"
468 data['password'] = "password"
470 data['username'] = "username"
471 data['password'] = "password"
473 for sharename, sharedata in mounts.items():
474 if sharedata['ip'] == selection[2].strip() and sharedata['sharedir'] == selection[3].strip():
476 self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
478 def MountEditClosed(self, returnValue = None):
479 if returnValue == None:
480 self.updateNetworkList()
482 class ScanIP(Screen, ConfigListScreen):
484 <screen name="ScanIP" position="center,center" size="560,80" title="Scan IP" >
485 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
486 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
487 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
488 <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" />
489 <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" />
490 <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" />
491 <widget name="config" position="5,50" size="540,25" scrollbarMode="showOnDemand" />
494 def __init__(self, session):
495 Screen.__init__(self, session)
496 self.session = session
498 self["key_red"] = StaticText(_("Cancel"))
499 self["key_green"] = StaticText(_("Scan NFS share"))
500 self["key_yellow"] = StaticText(_("Scan range"))
502 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
508 "yellow": self.goAddress,
511 self.ipAddress = ConfigIP(default=[0,0,0,0])
513 ConfigListScreen.__init__(self, [
514 getConfigListEntry(_("IP Address"), self.ipAddress),
517 self.onLayoutFinish.append(self.layoutFinished)
520 self.close((None,None))
522 def layoutFinished(self):
523 self.setWindowTitle()
525 def setWindowTitle(self):
526 self.setTitle(_("Enter IP to scan..."))
529 if self.ipAddress.getText() != "0.0.0.0":
530 self.close((self.ipAddress.getText(), "address"))
535 if self.ipAddress.getText() != "0.0.0.0":
536 self.close((self.ipAddress.getText(), "nfs"))