1 from zope
.interface
import implements
3 from twisted
.python
import usage
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
14 from qwebirc
.root
import RootSite
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"],
27 optFlags
= [["notracebacks", "n", "Display tracebacks in broken web pages. " +
28 "Displaying tracebacks to users may be security risk!"],
31 def postOptions(self
):
34 get_ssl_factory_factory()
36 raise usage
.UsageError("SSL support not installed")
38 class FlashPolicyProtocol(protocol
.Protocol
, policies
.TimeoutMixin
):
41 def dataReceived(self
, data
):
42 if data
== '<policy-file-request/>\0':
43 self
.transport
.write(self
.factory
.response_body
)
44 self
.transport
.loseConnection()
48 p
= self
.factory
.site
.buildProtocol(self
.transport
.client
)
49 p
.transport
= self
.transport
50 self
.transport
.protocol
= p
55 class FlashPolicyFactory(protocol
.ServerFactory
):
56 protocol
= FlashPolicyProtocol
58 def __init__(self
, site
):
60 base_url
= urlparse
.urlparse(config
.BASE_URL
)
63 if base_url
.scheme
== "http":
65 elif base_url
.scheme
== "https":
68 raise Exception("Unknown scheme: " + base_url
.scheme
)
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'
75 class QWebIRCServiceMaker(object):
76 implements(IServiceMaker
, IPlugin
)
78 description
= "QuakeNet web-based IRC client"
81 def makeService(self
, config
):
83 site
= RootSite(config
['staticpath'], logPath
=config
['logfile'])
85 site
= RootSite(config
['staticpath'])
87 site
.displayTracebacks
= not config
["notracebacks"]
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'])
92 i
= internet
.TCPServer(int(config
['port']), FlashPolicyFactory(site
), interface
=config
['ip'])
96 def get_ssl_factory_factory():
97 from twisted
.internet
.ssl
import DefaultOpenSSLContextFactory
98 class ChainingOpenSSLContextFactory(DefaultOpenSSLContextFactory
):
99 def __init__(self
, *args
, **kwargs
):
101 if kwargs
.has_key("certificateChainFile"):
102 self
.chain
= kwargs
["certificateChainFile"]
103 del kwargs
["certificateChainFile"]
105 DefaultOpenSSLContextFactory
.__init
__(self
, *args
, **kwargs
)
107 def cacheContext(self
):
108 DefaultOpenSSLContextFactory
.cacheContext(self
)
110 self
._context
.use_certificate_chain_file(self
.chain
)
111 self
._context
.use_privatekey_file(self
.privateKeyFileName
)
113 return ChainingOpenSSLContextFactory
115 serviceMaker
= QWebIRCServiceMaker()