]> jfr.im git - irc/quakenet/qwebirc.git/blob - twisted/plugins/webirc.py
add support for flash websockets (including flash policy server) -- wss untested
[irc/quakenet/qwebirc.git] / twisted / plugins / webirc.py
1 from zope.interface import implements
2
3 from twisted.python import usage
4
5 from twisted.internet import task, protocol
6 from twisted.protocols import basic, policies
7 from twisted.plugin import IPlugin
8 from twisted.application.service import IServiceMaker
9 from twisted.application import internet, strports
10 from twisted.web import static, server
11 import urlparse
12 import urllib
13
14 from qwebirc.root import RootSite
15
16 class Options(usage.Options):
17 optParameters = [["port", "p", "9090","Port to start the server on."],
18 ["ip", "i", "0.0.0.0", "IP address to listen on."],
19 ["logfile", "l", None, "Path to web CLF (Combined Log Format) log file."],
20 ["https", None, None, "Port to listen on for Secure HTTP."],
21 ["certificate", "c", "server.pem", "SSL certificate to use for HTTPS. "],
22 ["privkey", "k", "server.pem", "SSL certificate to use for HTTPS."],
23 ["certificate-chain", "C", None, "Chain SSL certificate"],
24 ["staticpath", "s", "static", "Path to static content"],
25 ]
26
27 optFlags = [["notracebacks", "n", "Display tracebacks in broken web pages. " +
28 "Displaying tracebacks to users may be security risk!"],
29 ]
30
31 def postOptions(self):
32 if self['https']:
33 try:
34 get_ssl_factory_factory()
35 except ImportError:
36 raise usage.UsageError("SSL support not installed")
37
38 class FlashPolicyProtocol(protocol.Protocol, policies.TimeoutMixin):
39 timeOut = 5
40
41 def dataReceived(self, data):
42 if data == '<policy-file-request/>\0':
43 self.transport.write(self.factory.response_body)
44 self.transport.loseConnection()
45 return
46 else:
47 self.setTimeout(None)
48 p = self.factory.site.buildProtocol(self.transport.client)
49 p.transport = self.transport
50 self.transport.protocol = p
51 p.connectionMade()
52 p.dataReceived(data)
53
54
55 class FlashPolicyFactory(protocol.ServerFactory):
56 protocol = FlashPolicyProtocol
57
58 def __init__(self, site):
59 import config
60 base_url = urlparse.urlparse(config.BASE_URL)
61 port = base_url.port
62 if port is None:
63 if base_url.scheme == "http":
64 port = 80
65 elif base_url.scheme == "https":
66 port = 443
67 else:
68 raise Exception("Unknown scheme: " + base_url.scheme)
69
70 self.site = site
71 self.response_body = """<cross-domain-policy>
72 <allow-access-from domain="%s" to-ports="%d" />
73 </cross-domain-policy>""" % (urllib.quote(base_url.hostname), port) + '\0'
74
75 class QWebIRCServiceMaker(object):
76 implements(IServiceMaker, IPlugin)
77 tapname = "qwebirc"
78 description = "QuakeNet web-based IRC client"
79 options = Options
80
81 def makeService(self, config):
82 if config['logfile']:
83 site = RootSite(config['staticpath'], logPath=config['logfile'])
84 else:
85 site = RootSite(config['staticpath'])
86
87 site.displayTracebacks = not config["notracebacks"]
88 if config['https']:
89 ssl_factory = get_ssl_factory_factory()
90 i = internet.SSLServer(int(config['https']), FlashPolicyFactory(site), ssl_factory(config['privkey'], config['certificate'], certificateChainFile=config["certificate-chain"]), interface=config['ip'])
91 else:
92 i = internet.TCPServer(int(config['port']), FlashPolicyFactory(site), interface=config['ip'])
93
94 return i
95
96 def get_ssl_factory_factory():
97 from twisted.internet.ssl import DefaultOpenSSLContextFactory
98 class ChainingOpenSSLContextFactory(DefaultOpenSSLContextFactory):
99 def __init__(self, *args, **kwargs):
100 self.chain = None
101 if kwargs.has_key("certificateChainFile"):
102 self.chain = kwargs["certificateChainFile"]
103 del kwargs["certificateChainFile"]
104
105 DefaultOpenSSLContextFactory.__init__(self, *args, **kwargs)
106
107 def cacheContext(self):
108 DefaultOpenSSLContextFactory.cacheContext(self)
109 if self.chain:
110 self._context.use_certificate_chain_file(self.chain)
111 self._context.use_privatekey_file(self.privateKeyFileName)
112
113 return ChainingOpenSSLContextFactory
114
115 serviceMaker = QWebIRCServiceMaker()