add Message send to Menu
[enigma2-plugins.git] / webinterface / src / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2
3 from twisted.internet import reactor
4 from twisted.web2 import server, channel, static, resource, stream, http_headers, responsecode, http
5 from twisted.python import util
6 import webif
7 import WebIfConfig  
8 import os
9
10
11 from Components.config import config, ConfigSubsection, ConfigInteger,ConfigYesNo
12
13 config.plugins.Webinterface = ConfigSubsection()
14 config.plugins.Webinterface.enable = ConfigYesNo(default = False)
15 config.plugins.Webinterface.port = ConfigInteger(80,limits = (1, 999))
16 config.plugins.Webinterface.includehdd = ConfigYesNo(default = False)
17
18 sessions = [ ]
19
20 # set DEBUG to True, if twisted should write logoutput to a file.
21 DEBUG = False 
22 DEBUGFILE= "/tmp/twisted.log"
23
24 # Passwordprotection Test
25 # set it only to True, if you have a patched wrapper.py
26 # see http://twistedmatrix.com/trac/ticket/2041
27 # in /usr/lib/python2.4/site-packages/twisted/web2/auth/wrapper.py
28 # The solution is to change this line
29 #       
30 #       return self.authenticate(req), seg[1:]
31 # into this
32 #       return self.authenticate(req), seg
33 PASSWORDPROTECTION = False
34 PASSWORDPROTECTION_pwd = "root"
35 PASSWORDPROTECTION_mode = "sha"; 
36 # twisted supports more than sha ('md5','md5-sess','sha')
37 # but only sha works for me, but IE 
38 # sha, Firefox=ok, Opera=ok, wget=ok, ie=not ok
39 # md5-sess, firefox=not ok, opera=not ok,wget=ok, ie=not ok
40 # md5 same as md5-sess 
41
42 def startWebserver():
43         class ScreenPage(resource.Resource):
44                 def __init__(self, path):
45                         self.path = path
46                         
47                         
48                 def render(self, req):
49                         global sessions
50                         if sessions == [ ]:
51                                 return http.Response(responsecode.OK, stream="please wait until enigma has booted")
52
53                         class myProducerStream(stream.ProducerStream):
54                                 closed_callback = None
55
56                                 def close(self):
57                                         if self.closed_callback:
58                                                 self.closed_callback()
59                                         stream.ProducerStream.close(self)
60
61                         if os.path.isfile(self.path):
62                                 s=myProducerStream()
63                                 webif.renderPage(s, self.path, req, sessions[0])  # login?
64                                 return http.Response(responsecode.OK,stream=s)
65                         else:
66                                 return http.Response(responsecode.NOT_FOUND)
67                         
68                 def locateChild(self, request, segments):
69                         path = self.path+'/'+'/'.join(segments)
70                         if path[-1:] == "/":
71                                 path += "index.html"
72                         path +=".xml"
73                         return ScreenPage(path), ()
74                 
75         class Toplevel(resource.Resource):
76                 addSlash = True
77
78                 def render(self, req):
79                         fp = open(util.sibpath(__file__, "web-data")+"/index.html")
80                         s = fp.read()
81                         fp.close()
82                         return http.Response(responsecode.OK, {'Content-type': http_headers.MimeType('text', 'html')},stream=s)
83
84                 child_web = ScreenPage(util.sibpath(__file__, "web")) # "/web/*"
85                 child_webdata = static.File(util.sibpath(__file__, "web-data")) # FIXME: web-data appears as webdata
86
87         toplevel = Toplevel()
88         if config.plugins.Webinterface.includehdd.value:
89                 toplevel.putChild("hdd",static.File("/hdd"))
90         
91         if PASSWORDPROTECTION is False:
92                 site = server.Site(toplevel)
93         else:
94                 from twisted.cred.portal import Portal
95                 from twisted.cred import checkers
96                 from twisted.web2.auth import digest, basic, wrapper
97                 from zope.interface import Interface, implements
98                 from twisted.cred import portal
99                 class IHTTPUser(Interface):
100                         pass
101
102                 class HTTPUser(object):
103                         implements(IHTTPUser)
104
105                 class HTTPAuthRealm(object):
106                         implements(portal.IRealm)
107                         def requestAvatar(self, avatarId, mind, *interfaces):
108                                 if IHTTPUser in interfaces:
109                                         return IHTTPUser, HTTPUser()
110                                 raise NotImplementedError("Only IHTTPUser interface is supported")
111
112                 portal = Portal(HTTPAuthRealm())
113                 checker = checkers.InMemoryUsernamePasswordDatabaseDontUse(root=PASSWORDPROTECTION_pwd)
114                 portal.registerChecker(checker)
115                 root = wrapper.HTTPAuthResource(toplevel,
116                                         (basic.BasicCredentialFactory('DM7025'),digest.DigestCredentialFactory(PASSWORDPROTECTION_mode,'DM7025')),
117                                         portal, (IHTTPUser,))
118                 site = server.Site(root)
119         print "starting Webinterface on port",config.plugins.Webinterface.port.value
120         reactor.listenTCP(config.plugins.Webinterface.port.value, channel.HTTPFactory(site))
121
122
123 def autostart(reason, **kwargs):
124         if "session" in kwargs:
125                 global sessions
126                 sessions.append(kwargs["session"])
127                 return
128
129         if reason == 0:
130                 try:
131                         """
132                          in normal console output, twisted will print only the first Traceback.
133                          is this a bug in twisted or a conflict with enigma2?
134                          with this option enabled, twisted will print all TB to the logfile
135                          use tail -f <file> to view this log
136                         """
137                         if DEBUG:
138                                 from twisted.python.log import startLogging
139                                 print "start twisted logfile, writing to %s" % DEBUGFILE 
140                                 startLogging(open(DEBUGFILE,'w'))
141                         
142                         if config.plugins.Webinterface.enable.value:
143                                 startWebserver()
144                         else:
145                                 print "not starting Webinterface"
146                 except ImportError:
147                         print "twisted not available, not starting web services"
148                         
149 def openconfig(session, **kwargs):
150         session.open(WebIfConfig.WebIfConfigScreen)
151
152 def Plugins(**kwargs):
153         return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
154                     PluginDescriptor(name=_("Webinterface"), description=_("Configuration for the Webinterface"),where = [PluginDescriptor.WHERE_PLUGINMENU], fnc = openconfig)]