# -*- coding: utf-8 -*-
# for localized messages
#from __init__ import _
from enigma import eTimer, eEnv, eNetworkManager
from Screens.Screen import Screen
from Screens.MessageBox import MessageBox
from Components.ActionMap import ActionMap
from Components.Sources.List import List
from Components.Sources.StaticText import StaticText
from Components.Network import iNetworkInfo, NetworkInterface
from Components.config import getConfigListEntry, ConfigIP
from Components.ConfigList import ConfigListScreen
from Tools.Directories import resolveFilename, SCOPE_PLUGINS
from Tools.LoadPixmap import LoadPixmap
from Tools.Log import Log
from cPickle import dump, load
from os import path as os_path, stat, mkdir, remove
from time import time
from stat import ST_MTIME
import netscan
from MountManager import AutoMountManager
from AutoMount import iAutoMount
from MountEdit import AutoMountEdit
from UserDialog import UserDialog
def write_cache(cache_file, cache_data):
#Does a cPickle dump
if not os_path.isdir( os_path.dirname(cache_file) ):
try:
mkdir( os_path.dirname(cache_file) )
except OSError:
print os_path.dirname(cache_file), '[Networkbrowser] is a file'
fd = open(cache_file, 'w')
dump(cache_data, fd, -1)
fd.close()
def valid_cache(cache_file, cache_ttl):
#See if the cache file exists and is still living
try:
mtime = stat(cache_file)[ST_MTIME]
except:
return 0
curr_time = time()
if (curr_time - mtime) > cache_ttl:
return 0
else:
return 1
def load_cache(cache_file):
#Does a cPickle load
fd = open(cache_file)
cache_data = load(fd)
fd.close()
return cache_data
class NetworkDescriptor:
def __init__(self, name = "NetworkServer", description = ""):
self.name = name
self.description = description
class NetworkBrowser(Screen):
skin = """
{"template": [
MultiContentEntryPixmapAlphaTest(pos = (0, 0), size = (48, 48), png = 1), # index 1 is the expandable/expanded/verticalline icon
MultiContentEntryText(pos = (50, 4), size = (420, 26), font=2, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the Hostname
MultiContentEntryText(pos = (140, 5), size = (320, 25), font=0, flags = RT_HALIGN_LEFT, text = 3), # index 3 is the sharename
MultiContentEntryText(pos = (140, 26), size = (320, 17), font=1, flags = RT_HALIGN_LEFT, text = 4), # index 4 is the sharedescription
MultiContentEntryPixmapAlphaTest(pos = (45, 0), size = (48, 48), png = 5), # index 5 is the nfs/cifs icon
MultiContentEntryPixmapAlphaTest(pos = (90, 0), size = (48, 48), png = 6), # index 6 is the isMounted icon
],
"fonts": [gFont("Regular", 20),gFont("Regular", 14),gFont("Regular", 24)],
"itemHeight": 50
}
"""
def __init__(self, session, iface,plugin_path):
Screen.__init__(self, session)
self.skin_path = plugin_path
self.session = session
self.iface = iface
services = eNetworkManager.getInstance().getServices()
for service in services:
key = self.getServiceIF(service)
if key != None:
self.iface = key
if self.iface is None:
self.iface = 'eth0'
self.networklist = None
self.device = None
self.mounts = None
self.expanded = []
self.cache_ttl = 604800 #Seconds cache is considered valid, 7 Days should be ok
self.cache_file = eEnv.resolve("${sysconfdir}/enigma2/networkbrowser.cache") #Path to cache directory
self["key_red"] = StaticText(_("Close"))
self["key_green"] = StaticText(_("Mounts management"))
self["key_yellow"] = StaticText(_("Rescan"))
self["key_blue"] = StaticText(_("Expert"))
self["infotext"] = StaticText(_("Press OK to mount!"))
self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
{
"ok": self.go,
"back": self.close,
"red": self.close,
"green": self.keyGreen,
"yellow": self.keyYellow,
"blue": self.keyBlue,
})
self.list = []
self.statuslist = []
self.listindex = 0
self["list"] = List(self.list)
self["list"].onSelectionChanged.append(self.selectionChanged)
self.onLayoutFinish.append(self.startRun)
self.onShown.append(self.setWindowTitle)
self.onClose.append(self.cleanup)
self.Timer = eTimer()
self.Timer_conn = self.Timer.timeout.connect(self.TimerFire)
def getServiceIF(self, service):
key = None
if service.state() == eNetworkManager.STATE_ONLINE:
iface = NetworkInterface(service)
key = iface.ethernet.interface
return key
def cleanup(self):
del self.Timer
iAutoMount.stopMountConsole()
def startRun(self):
self.expanded = []
self.setStatus('update')
self.mounts = iAutoMount.getMountsList()
self["infotext"].setText("")
self.vc = valid_cache(self.cache_file, self.cache_ttl)
if self.cache_ttl > 0 and self.vc != 0:
self.process_NetworkIPs()
else:
self.Timer.start(3000)
def TimerFire(self):
self.Timer.stop()
self.process_NetworkIPs()
def setWindowTitle(self):
self.setTitle(_("Browse network neighbourhood"))
def keyGreen(self):
self.session.open(AutoMountManager, None, self.skin_path)
def keyYellow(self):
if (os_path.exists(self.cache_file) == True):
remove(self.cache_file)
self.startRun()
def keyBlue(self):
self.session.openWithCallback(self.scanIPclosed,ScanIP)
def scanIPclosed(self,result):
if result[0]:
if result[1] == "address":
print "[Networkbrowser] got IP:",result[1]
nwlist = []
nwlist.append(netscan.netInfo(result[0] + "/24"))
self.networklist += nwlist[0]
elif result[1] == "nfs":
self.networklist.append(['host', result[0], result[0] , '00:00:00:00:00:00', result[0], 'Master Browser'])
if len(self.networklist) > 0:
write_cache(self.cache_file, self.networklist)
self.updateHostsList()
def setStatus(self,status = None):
if status:
self.statuslist = []
if status == 'update':
statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/update.png"))
self.statuslist.append(( ['info'], statuspng, _("Searching your network. Please wait..."), None, None, None, None ))
self['list'].setList(self.statuslist)
elif status == 'error':
statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/error.png"))
self.statuslist.append(( ['info'], statuspng, _("No network devices found!"), None, None, None, None ))
self['list'].setList(self.statuslist)
def process_NetworkIPs(self):
self.inv_cache = 0
self.vc = valid_cache(self.cache_file, self.cache_ttl)
if self.cache_ttl > 0 and self.vc != 0:
print '[Networkbrowser] Loading network cache from ',self.cache_file
try:
self.networklist = load_cache(self.cache_file)
except:
self.inv_cache = 1
if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
print '[Networkbrowser] Getting fresh network list'
self.networklist = self.getNetworkIPs()
write_cache(self.cache_file, self.networklist)
if len(self.networklist) > 0:
self.updateHostsList()
else:
self.setStatus('error')
def getNetworkIPs(self):
nwlist = []
sharelist = []
self.IP = iNetworkInfo.getConfiguredInterfaces()[self.iface].ipv4.address.split(".")
if len(self.IP):
strIP = "%s.0/24" %( ".".join(self.IP[0:3]) )
Log.i(strIP)
nwlist.append(netscan.netInfo(strIP))
tmplist = nwlist[0]
return tmplist
def getNetworkShares(self,hostip,hostname,devicetype):
sharelist = []
self.sharecache_file = None
self.sharecache_file = eEnv.resolve("${sysconfdir}/enigma2/") + hostname.strip() + '.cache' #Path to cache directory
if os_path.exists(self.sharecache_file):
print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
try:
self.hostdata = load_cache(self.sharecache_file)
username = self.hostdata['username']
password = self.hostdata['password']
except:
username = "username"
password = "password"
else:
username = "username"
password = "password"
if devicetype == 'unix':
smblist=netscan.smbShare(hostip,hostname,username,password)
for x in smblist:
if len(x) == 6:
if x[3] != 'IPC$':
sharelist.append(x)
nfslist=netscan.nfsShare(hostip,hostname)
for x in nfslist:
if len(x) == 6:
sharelist.append(x)
else:
smblist=netscan.smbShare(hostip,hostname,username,password)
for x in smblist:
if len(x) == 6:
if x[3] != 'IPC$':
sharelist.append(x)
return sharelist
def updateHostsList(self):
self.list = []
self.network = {}
for x in self.networklist:
if not self.network.has_key(x[2]):
self.network[x[2]] = []
self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
for x in self.network.keys():
hostentry = self.network[x][0][1]
name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
if len(self.list):
for entry in self.list:
entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
self.list.sort(key=lambda x: x[0][2])
for entry in self.list:
entry[0][2]= entry[0][2].replace(" ", "")
self["list"].setList(self.list)
self["list"].setIndex(self.listindex)
def updateNetworkList(self):
self.list = []
self.network = {}
self.mounts = iAutoMount.getMountsList() # reloading mount list
for x in self.networklist:
if not self.network.has_key(x[2]):
self.network[x[2]] = []
self.network[x[2]].append((NetworkDescriptor(name = x[1], description = x[2]), x))
self.network.keys().sort()
for x in self.network.keys():
if self.network[x][0][1][3] == '00:00:00:00:00:00':
self.device = 'unix'
else:
self.device = 'windows'
if x in self.expanded:
networkshares = self.getNetworkShares(x,self.network[x][0][1][1].strip(),self.device)
hostentry = self.network[x][0][1]
name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
expandedIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
self.list.append(( hostentry, expandedIcon, name, None, None, None, None ))
for share in networkshares:
self.list.append(self.BuildNetworkShareEntry(share))
else: # HOSTLIST - VIEW
hostentry = self.network[x][0][1]
name = hostentry[2] + " ( " +hostentry[1].strip() + " )"
expandableIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/host.png"))
self.list.append(( hostentry, expandableIcon, name, None, None, None, None ))
if len(self.list):
for entry in self.list:
entry[0][2]= "%3s.%3s.%3s.%3s" % tuple(entry[0][2].split("."))
self.list.sort(key=lambda x: x[0][2])
for entry in self.list:
entry[0][2]= entry[0][2].replace(" ", "")
self["list"].setList(self.list)
self["list"].setIndex(self.listindex)
def BuildNetworkShareEntry(self,share):
verticallineIcon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/verticalLine.png"))
sharetype = share[0]
localsharename = share[1]
sharehost = share[2]
if sharetype == 'smbShare':
sharedir = share[3]
sharedescription = share[5]
else:
sharedir = share[4]
sharedescription = share[3]
if sharetype == 'nfsShare':
newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-nfs.png"))
else:
newpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/i-smb.png"))
self.isMounted = False
for sharename, sharedata in self.mounts.items():
if sharedata['ip'] == sharehost:
if sharetype == 'nfsShare' and sharedata['mounttype'] == 'nfs':
if sharedir == sharedata['sharedir']:
if sharedata["isMounted"] is True:
self.isMounted = True
if sharetype == 'smbShare' and sharedata['mounttype'] == 'cifs':
if sharedir == sharedata['sharedir']:
if sharedata["isMounted"] is True:
self.isMounted = True
if self.isMounted is True:
isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/ok.png"))
else:
isMountedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkBrowser/icons/cancel.png"))
return((share, verticallineIcon, None, sharedir, sharedescription, newpng, isMountedpng))
def selectionChanged(self):
current = self["list"].getCurrent()
self.listindex = self["list"].getIndex()
if current:
if len(current[0]) >= 2:
if current[0][0] in ("nfsShare", "smbShare"):
self["infotext"].setText(_("Press OK to mount this share!"))
else:
selectedhost = current[0][2]
if selectedhost in self.expanded:
self["infotext"].setText(_("Press OK to collapse this host"))
else:
self["infotext"].setText(_("Press OK to expand this host"))
def go(self):
sel = self["list"].getCurrent()
if sel is None:
return
if len(sel[0]) <= 1:
return
selectedhost = sel[0][2]
selectedhostname = sel[0][1]
self.hostcache_file = None
if sel[0][0] == 'host': # host entry selected
if selectedhost in self.expanded:
self.expanded.remove(selectedhost)
self.updateNetworkList()
else:
self.hostcache_file = None
self.hostcache_file = eEnv.resolve("${sysconfdir}/enigma2/") + selectedhostname.strip() + '.cache' #Path to cache directory
if os_path.exists(self.hostcache_file):
print '[Networkbrowser] Loading userinfo cache from ',self.hostcache_file
try:
self.hostdata = load_cache(self.hostcache_file)
self.passwordQuestion(False)
except:
self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
else:
self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
if sel[0][0] == 'nfsShare': # share entry selected
print '[Networkbrowser] sel nfsShare'
self.openMountEdit(sel[0])
if sel[0][0] == 'smbShare': # share entry selected
print '[Networkbrowser] sel cifsShare'
self.hostcache_file = None
self.hostcache_file = eEnv.resolve("${sysconfdir}/enigma2/") + selectedhostname.strip() + '.cache' #Path to cache directory
if os_path.exists(self.hostcache_file):
print '[Networkbrowser] userinfo found from ',self.sharecache_file
self.openMountEdit(sel[0])
else:
self.session.openWithCallback(self.passwordQuestion, MessageBox, (_("Do you want to enter a username and password for this host?\n") ) )
def passwordQuestion(self, ret = False):
sel = self["list"].getCurrent()
selectedhost = sel[0][2]
selectedhostname = sel[0][1]
if (ret == True):
self.session.openWithCallback(self.UserDialogClosed, UserDialog, self.skin_path, selectedhostname.strip())
else:
if sel[0][0] == 'host': # host entry selected
if selectedhost in self.expanded:
self.expanded.remove(selectedhost)
else:
self.expanded.append(selectedhost)
self.updateNetworkList()
if sel[0][0] == 'nfsShare': # share entry selected
self.openMountEdit(sel[0])
if sel[0][0] == 'smbShare': # share entry selected
self.openMountEdit(sel[0])
def UserDialogClosed(self, *ret):
if ret is not None and len(ret):
self.go()
def openMountEdit(self, selection):
if selection is not None and len(selection):
mounts = iAutoMount.getMountsList()
if selection[0] == 'nfsShare': # share entry selected
#Initialize blank mount enty
data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
# add data
data['mounttype'] = 'nfs'
data['active'] = True
data['ip'] = selection[2]
data['sharename'] = selection[1]
data['sharedir'] = selection[4]
data['options'] = "rw,nolock,tcp"
for sharename, sharedata in mounts.items():
if sharedata['ip'] == selection[2] and sharedata['sharedir'] == selection[4]:
data = sharedata
self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
if selection[0] == 'smbShare': # share entry selected
#Initialize blank mount enty
data = { 'isMounted': False, 'active': False, 'ip': False, 'sharename': False, 'sharedir': False, 'username': False, 'password': False, 'mounttype' : False, 'options' : False }
# add data
data['mounttype'] = 'cifs'
data['active'] = True
data['ip'] = selection[2]
data['sharename'] = selection[1]
data['sharedir'] = selection[3]
data['options'] = "rw"
self.sharecache_file = None
self.sharecache_file = eEnv.resolve("${sysconfdir}/enigma2/") + selection[1].strip() + '.cache' #Path to cache directory
if os_path.exists(self.sharecache_file):
print '[Networkbrowser] Loading userinfo from ',self.sharecache_file
try:
self.hostdata = load_cache(self.sharecache_file)
data['username'] = self.hostdata['username']
data['password'] = self.hostdata['password']
except:
data['username'] = "username"
data['password'] = "password"
else:
data['username'] = "username"
data['password'] = "password"
for sharename, sharedata in mounts.items():
if sharedata['ip'] == selection[2].strip() and sharedata['sharedir'] == selection[3].strip():
data = sharedata
self.session.openWithCallback(self.MountEditClosed,AutoMountEdit, self.skin_path, data)
def MountEditClosed(self, returnValue = None):
if returnValue == None:
self.updateNetworkList()
class ScanIP(Screen, ConfigListScreen):
skin = """
"""
def __init__(self, session):
Screen.__init__(self, session)
self.session = session
self["key_red"] = StaticText(_("Cancel"))
self["key_green"] = StaticText(_("Scan NFS share"))
self["key_yellow"] = StaticText(_("Scan range"))
self["actions"] = ActionMap(["SetupActions", "ColorActions"],
{
"back": self.exit,
"red": self.exit,
"cancel": self.exit,
"green": self.goNfs,
"yellow": self.goAddress,
}, -1)
self.ipAddress = ConfigIP(default=[0,0,0,0])
ConfigListScreen.__init__(self, [
getConfigListEntry(_("IP Address"), self.ipAddress),
], self.session)
self.onLayoutFinish.append(self.layoutFinished)
def exit(self):
self.close((None,None))
def layoutFinished(self):
self.setWindowTitle()
def setWindowTitle(self):
self.setTitle(_("Enter IP to scan..."))
def goAddress(self):
if self.ipAddress.getText() != "0.0.0.0":
self.close((self.ipAddress.getText(), "address"))
else:
self.exit
def goNfs(self):
if self.ipAddress.getText() != "0.0.0.0":
self.close((self.ipAddress.getText(), "nfs"))
else:
self.exit