]> jfr.im git - irc/quakenet/qwebirc.git/blob - qwebirc/root.py
Merge pull request #350 from mas90/dnstweaks2
[irc/quakenet/qwebirc.git] / qwebirc / root.py
1 from twisted.protocols.policies import TimeoutMixin
2 from twisted.web import resource, server, static, http
3 from twisted.internet import error, reactor
4 import engines
5 import mimetypes
6 import config
7 import sigdebug
8 import re
9
10 class RootResource(resource.Resource):
11 def getChild(self, name, request):
12 if name == "":
13 name = "qui.html"
14 return self.primaryChild.getChild(name, request)
15
16 class WrappedRequest(server.Request):
17 ip_re = re.compile(r"^((25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})|(::|(([a-fA-F0-9]{1,4}):){7}(([a-fA-F0-9]{1,4}))|(:(:([a-fA-F0-9]{1,4})){1,6})|((([a-fA-F0-9]{1,4}):){1,6}:)|((([a-fA-F0-9]{1,4}):)(:([a-fA-F0-9]{1,4})){1,6})|((([a-fA-F0-9]{1,4}):){2}(:([a-fA-F0-9]{1,4})){1,5})|((([a-fA-F0-9]{1,4}):){3}(:([a-fA-F0-9]{1,4})){1,4})|((([a-fA-F0-9]{1,4}):){4}(:([a-fA-F0-9]{1,4})){1,3})|((([a-fA-F0-9]{1,4}):){5}(:([a-fA-F0-9]{1,4})){1,2})))$", re.IGNORECASE)
18 def validIP(self, ip):
19 m = self.ip_re.match(ip)
20 if m is None:
21 return False
22 return True
23
24 def _getClientIP(self):
25 # twisted.web.http.Request.getClientIP returns None if not IPv4;
26 # client.host has the real address
27
28 if not hasattr(self, "client") or not hasattr(self.client, "host"):
29 return None
30
31 real_ip = self.client.host
32
33 if real_ip[:7] == "::ffff:":
34 real_ip = real_ip[7:]
35
36 if not hasattr(config, "FORWARDED_FOR_HEADER"):
37 return real_ip
38
39 if real_ip not in config.FORWARDED_FOR_IPS:
40 return real_ip
41
42 fake_ips = self.getHeader(config.FORWARDED_FOR_HEADER)
43 if fake_ips is None:
44 return real_ip
45
46 fake_ip = fake_ips.split(",")[-1].strip()
47 if not self.validIP(fake_ip):
48 return real_ip
49
50 return fake_ip
51
52 def getClientIP(self):
53 ip = self._getClientIP()
54
55 if ip is None:
56 return None
57
58 # make absolutely sure that the address doesn't start with : before we
59 # try to use it as a string to the IRC server!
60 return ip.lstrip(":")
61
62 class HTTPChannel(http.HTTPChannel):
63 def timeoutConnection(self):
64 self.transport.abortConnection()
65
66 class RootSite(server.Site):
67 protocol = HTTPChannel
68
69 requestFactory = WrappedRequest
70
71 def __init__(self, path, *args, **kwargs):
72 root = RootResource()
73 kwargs["timeout"] = config.HTTP_REQUEST_TIMEOUT
74 server.Site.__init__(self, root, *args, **kwargs)
75 services = {}
76 services["StaticEngine"] = root.primaryChild = engines.StaticEngine(path)
77
78 def register(service, path, *args, **kwargs):
79 sobj = service("/" + path, *args, **kwargs)
80 services[service.__name__] = sobj
81 root.putChild(path, sobj)
82
83 register(engines.AJAXEngine, "e")
84 try:
85 register(engines.WebSocketEngine, "w")
86 except AttributeError:
87 pass
88 register(engines.AuthgateEngine, "auth")
89 register(engines.AdminEngine, "adminengine", services)
90
91 mimetypes.types_map[".ico"] = "image/vnd.microsoft.icon"