remove possibility to enable "webif" logging to file
[vuplus_dvbapp-plugin] / webinterface / src / plugin.py
index 50ed01e..f1fcbb6 100644 (file)
@@ -1,31 +1,33 @@
 Version = '$Header$';
-__version__ = "Beta 0.95.1"
+__version__ = "Beta 0.98.5"
 from Plugins.Plugin import PluginDescriptor
 from Components.config import config, ConfigSubsection, ConfigInteger,ConfigYesNo,ConfigText
 from Components.Network import Network
 
 from twisted.internet import reactor, defer
-from twisted.web2 import server, channel, static, resource, stream, http_headers, responsecode, http
+from twisted.web2 import server, channel, http
 from twisted.web2.auth import digest, basic, wrapper
 #from twisted.python import util
-from twisted.python.log import startLogging,discardLogs
+from twisted.python.log import startLogging
 from twisted.cred.portal import Portal, IRealm
 from twisted.cred import checkers, credentials, error
 from zope.interface import Interface, implements
 
-import webif
-import WebIfConfig  
-import os
+from WebIfConfig import WebIfConfigScreen
 
 from WebChilds.Toplevel import Toplevel
+
+from Tools.BoundFunction import boundFunction
+
 config.plugins.Webinterface = ConfigSubsection()
 config.plugins.Webinterface.enable = ConfigYesNo(default = True)
 config.plugins.Webinterface.port = ConfigInteger(80,limits = (1, 65536))
 config.plugins.Webinterface.includehdd = ConfigYesNo(default = False)
 config.plugins.Webinterface.useauth = ConfigYesNo(default = False) # False, because a std. images hasnt a rootpasswd set and so no login. and a login with a empty pwd makes no sense
-config.plugins.Webinterface.debug = ConfigYesNo(default = False) # False by default, not confgurable in GUI. Edit settingsfile directly if needed
+config.plugins.Webinterface.autowritetimer = ConfigYesNo(default = False)
+config.plugins.Webinterface.loadmovielength = ConfigYesNo(default = False)
 config.plugins.Webinterface.version = ConfigText(__version__) # used to make the versioninfo accessible enigma2-wide, not confgurable in GUI. 
+
 
 """
  set DEBUG to True, if twisted should write logoutput to a file.
@@ -34,56 +36,112 @@ config.plugins.Webinterface.version = ConfigText(__version__) # used to make the
  with this option enabled, twisted will print all TB to the logfile
  use tail -f <file> to view this log
 """
-                       
+
+# PLEASE DONT ENABLE LOGGING BY DEFAULT (OR COMMIT TO PLUGIN CVS)
+# AND DONT ADD CONFIG OPTIONS WHICH HELPS NORMAL USERS TO ENABLE
+# THIS KIND OF LOGGING !!!!!!!!!!!!! 
+# Twisted logging can't handle UTF8 correct,
+# and enigma2 internal completely use UTF8 (for debug messages too)             
+# so the twisted logging code self generates frequently blue screens 
+# at various places in enigma2(not only in Webif) and the reason 
+# of this crashes is NOT visible in the normal enigma2 crashlogs 
+# We have spent much time into debugging this          Ghost 2007/11/15
+
+DEBUG_TO_FILE=False
 
 DEBUGFILE= "/tmp/twisted.log"
 
-def stopWebserver():
-       reactor.disconnectAll()
+global running_defered,waiting_shutdown
+running_defered = []
+waiting_shutdown = 0
 
+class Closer:
+       counter = 0
+       def __init__(self,session, callback):
+               self.callback = callback
+               self.session = session
+               
+       def stop(self):
+               global running_defered
+               for d in running_defered:
+                       print "[WebIf] STOPPING reactor on interface ",d.interface," with port",d.port
+                       x = d.stopListening()
+                       try:
+                               x.addCallback(self.isDown)
+                               self.counter +=1
+                       except AttributeError:
+                               pass
+               running_defered = []
+               if self.counter <1:
+                       self.callback(self.session)
+               
+       def isDown(self,s):
+               self.counter-=1
+               if self.counter <1:
+                       self.callback(self.session)
+                       
+               
 def restartWebserver(session):
-       stopWebserver()
-       startWebserver(session)
+       try:
+               del session.mediaplayer
+               del session.messageboxanswer
+       except NameError:
+               pass
+       except AttributeError:
+               pass
 
-def startWebserver(session):
-       if config.plugins.Webinterface.enable.value is not True:
-               print "not starting Werbinterface"
-               return False
-       if config.plugins.Webinterface.debug.value:
-               print "start twisted logfile, writing to %s" % DEBUGFILE 
-               import sys
-               startLogging(open(DEBUGFILE,'w'))
-
-       toplevel = Toplevel(session)
-       if config.plugins.Webinterface.useauth.value is False:
-               site = server.Site(toplevel)
+       global running_defered
+       if len(running_defered) >0:
+               Closer(session,startWebserver).stop()
        else:
-               portal = Portal(HTTPAuthRealm())
-               portal.registerChecker(PasswordDatabase())
-               root = ModifiedHTTPAuthResource(toplevel,(basic.BasicCredentialFactory('DM7025'),),portal, (IHTTPUser,))
-               site = server.Site(root)
-       
-       # here we start the Toplevel without any username or password
-       # this allows access to all request over the iface 127.0.0.1 without any auth
-       localsite = server.Site(toplevel)
-       reactor.listenTCP(config.plugins.Webinterface.port.value, channel.HTTPFactory(localsite),interface='127.0.0.1')
+               startWebserver(session)
+
+def startWebserver(session):
+       global running_defered
+       try:
+               # variables, that are needed in the process
+               session.mediaplayer = None
+               session.messageboxanswer = None
+               
+               if config.plugins.Webinterface.enable.value is not True:
+                       print "not starting Werbinterface"
+                       return False
+               if DEBUG_TO_FILE:
+                       print "start twisted logfile, writing to %s" % DEBUGFILE 
+                       startLogging(open(DEBUGFILE,'w'))
        
-       # and here we make the Toplevel public to our external ifaces
-       # it depends on the config, if this is with auth support
-       # keep in mind, if we have a second external ip (like a wlan device), we have to do it in the same way for this iface too
-       nw = Network()
-       for adaptername in nw.ifaces:
-               extip = nw.ifaces[adaptername]['ip']
-               if nw.ifaces[adaptername]['up'] is True:
-                       extip = "%i.%i.%i.%i"%(extip[0],extip[1],extip[2],extip[3])
-                       print "[WebIf] starting Webinterface on port %s on interface %s with address %s"%(str(config.plugins.Webinterface.port.value),adaptername,extip)
-                       try:
-                               reactor.listenTCP(config.plugins.Webinterface.port.value, channel.HTTPFactory(site),interface=extip)
-                       except Exception,e:
-                               print "[WebIf] Error starting Webinterface on port %s on interface %s with address %s,because \n%s"%(str(config.plugins.Webinterface.port.value),adaptername,extip,e)
+               toplevel = Toplevel(session)
+               if config.plugins.Webinterface.useauth.value is False:
+                       site = server.Site(toplevel)
                else:
-                       print "[WebIf] found configured interface %s, but it is not running. so not starting a server on it ..." % adaptername
-       
+                       portal = Portal(HTTPAuthRealm())
+                       portal.registerChecker(PasswordDatabase())
+                       root = ModifiedHTTPAuthResource(toplevel,(basic.BasicCredentialFactory('DM7025'),),portal, (IHTTPUser,))
+                       site = server.Site(root)
+               
+               # here we start the Toplevel without any username or password
+               # this allows access to all request over the iface 127.0.0.1 without any auth
+               localsite = server.Site(toplevel)
+               d = reactor.listenTCP(config.plugins.Webinterface.port.value, channel.HTTPFactory(localsite),interface='127.0.0.1')
+               running_defered.append(d)
+               # and here we make the Toplevel public to our external ifaces
+               # it depends on the config, if this is with auth support
+               # keep in mind, if we have a second external ip (like a wlan device), we have to do it in the same way for this iface too
+               nw = Network()
+               for adaptername in nw.ifaces:
+                       extip = nw.ifaces[adaptername]['ip']
+                       if nw.ifaces[adaptername]['up'] is True:
+                               extip = "%i.%i.%i.%i"%(extip[0],extip[1],extip[2],extip[3])
+                               print "[WebIf] starting Webinterface on port %s on interface %s with address %s"%(str(config.plugins.Webinterface.port.value),adaptername,extip)
+                               try:
+                                       d = reactor.listenTCP(config.plugins.Webinterface.port.value, channel.HTTPFactory(site),interface=extip)
+                                       running_defered.append(d)
+                               except Exception,e:
+                                       print "[WebIf] Error starting Webinterface on port %s on interface %s with address %s,because \n%s"%(str(config.plugins.Webinterface.port.value),adaptername,extip,e)
+                       else:
+                               print "[WebIf] found configured interface %s, but it is not running. so not starting a server on it ..." % adaptername
+       except Exception,e:
+               print "\n\nSomething went wrong on starting the webif. May the following Line can help to find the error:\n",e,"\n\n"
 ####           
 def autostart(reason, **kwargs):
        if "session" in kwargs:
@@ -93,7 +151,7 @@ def autostart(reason, **kwargs):
                        print "[WebIf] twisted not available, not starting web services",e
                        
 def openconfig(session, **kwargs):
-       session.openWithCallback(configCB,WebIfConfig.WebIfConfigScreen)
+       session.openWithCallback(configCB,WebIfConfigScreen)
 
 def configCB(result,session):
        if result is True:
@@ -151,8 +209,11 @@ class HTTPAuthRealm(object):
                        return IHTTPUser, HTTPUser()
                raise NotImplementedError("Only IHTTPUser interface is supported")
 
-       
-import md5,time,string,crypt
+
+from string import find, split 
+from md5 import new as md5_new
+from crypt import crypt
+
 DES_SALT = list('./0123456789' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz') 
 def getpwnam(name, pwfile=None):
     """Return pasword database entry for the given user name.
@@ -177,7 +238,7 @@ def getpwnam(name, pwfile=None):
 def passcrypt(passwd, salt=None, method='des', magic='$1$'):
     """Encrypt a string according to rules in crypt(3)."""
     if method.lower() == 'des':
-           return crypt.crypt(passwd, salt)
+           return crypt(passwd, salt)
     elif method.lower() == 'md5':
        return passcrypt_md5(passwd, salt, magic)
     elif method.lower() == 'clear':
@@ -198,7 +259,7 @@ def check_passwd(name, passwd, pwfile=None):
     if not enc_passwd:
         return 0
     elif len(enc_passwd) >= 3 and enc_passwd[:3] == '$1$':
-        salt = enc_passwd[3:string.find(enc_passwd, '$', 3)]
+        salt = enc_passwd[3:find(enc_passwd, '$', 3)]
         return enc_passwd == passcrypt(passwd, salt, 'md5')
        
     else:
@@ -222,15 +283,15 @@ def passcrypt_md5(passwd, salt=None, magic='$1$'):
         salt = salt[len(magic):]
 
     # salt only goes up to first '$'
-    salt = string.split(salt, '$')[0]
+    salt = split(salt, '$')[0]
     # limit length of salt to 8
     salt = salt[:8]
 
-    ctx = md5.new(passwd)
+    ctx = md5_new(passwd)
     ctx.update(magic)
     ctx.update(salt)
     
-    ctx1 = md5.new(passwd)
+    ctx1 = md5_new(passwd)
     ctx1.update(salt)
     ctx1.update(passwd)
     
@@ -252,7 +313,7 @@ def passcrypt_md5(passwd, salt=None, magic='$1$'):
     final = ctx.digest()
     
     for i in range(1000):
-       ctx1 = md5.new()
+       ctx1 = md5_new()
        if i & 1:
            ctx1.update(passwd)
        else: