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