]>
Commit | Line | Data |
---|---|---|
940227cb MT |
1 | #!/usr/bin/python |
2 | ||
cc3b928d | 3 | import datetime |
66862195 | 4 | import dateutil.parser |
11347e46 | 5 | import http.client |
a69e87a1 | 6 | import ipaddress |
47ed77ed | 7 | import logging |
940227cb MT |
8 | import time |
9 | import tornado.locale | |
10 | import tornado.web | |
11 | ||
a95c2f97 | 12 | from .. import util |
60024cc8 | 13 | |
940227cb | 14 | class BaseHandler(tornado.web.RequestHandler): |
76582150 MT |
15 | # Indicates if content should always be cached, |
16 | # even when a user is logged in | |
17 | always_cache = False | |
18 | ||
b592d7c8 MT |
19 | def prepare(self): |
20 | # Mark this as private when someone is logged in | |
76582150 | 21 | if not self.always_cache and self.current_user: |
b592d7c8 MT |
22 | self.add_header("Cache-Control", "private") |
23 | ||
f6ed3d4d MT |
24 | def set_expires(self, seconds): |
25 | # For HTTP/1.1 | |
b592d7c8 | 26 | self.add_header("Cache-Control", "max-age=%s, must-revalidate" % seconds) |
f6ed3d4d MT |
27 | |
28 | # For HTTP/1.0 | |
29 | expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=seconds) | |
b592d7c8 | 30 | self.add_header("Expires", expires) |
f6ed3d4d | 31 | |
37ed7c3c MT |
32 | def write_error(self, status_code, **kwargs): |
33 | # Translate code into message | |
34 | try: | |
11347e46 | 35 | message = http.client.responses[status_code] |
37ed7c3c MT |
36 | except KeyError: |
37 | message = None | |
38 | ||
39 | self.render("error.html", status_code=status_code, message=message, **kwargs) | |
40 | ||
4ca1a601 MT |
41 | @property |
42 | def hostname(self): | |
43 | # Remove the development prefix | |
44 | return self.request.host.replace(".dev.", ".") | |
45 | ||
bff08cb0 MT |
46 | def get_template_namespace(self): |
47 | ns = tornado.web.RequestHandler.get_template_namespace(self) | |
48 | ||
911064cf | 49 | now = datetime.date.today() |
cc3b928d | 50 | |
bff08cb0 | 51 | ns.update({ |
5613b94b | 52 | "debug" : self.application.settings.get("debug", False), |
a95c2f97 MT |
53 | "format_size" : util.format_size, |
54 | "format_time" : util.format_time, | |
4ca1a601 | 55 | "hostname" : self.hostname, |
911064cf MT |
56 | "now" : now, |
57 | "year" : now.year, | |
bff08cb0 | 58 | }) |
940227cb | 59 | |
bff08cb0 | 60 | return ns |
940227cb | 61 | |
9068dba1 MT |
62 | def get_remote_ip(self): |
63 | # Fix for clients behind a proxy that sends "X-Forwarded-For". | |
66862195 | 64 | remote_ips = self.request.remote_ip.split(", ") |
494d80e6 | 65 | |
66862195 MT |
66 | for remote_ip in remote_ips: |
67 | try: | |
a69e87a1 | 68 | addr = ipaddress.ip_address(remote_ip) |
66862195 MT |
69 | except ValueError: |
70 | # Skip invalid IP addresses. | |
71 | continue | |
9068dba1 | 72 | |
66862195 MT |
73 | # Check if the given IP address is from a |
74 | # private network. | |
75 | if addr.is_private: | |
76 | continue | |
9068dba1 | 77 | |
66862195 | 78 | return remote_ip |
9068dba1 | 79 | |
494d80e6 MT |
80 | # Return the last IP if nothing else worked |
81 | return remote_ips.pop() | |
82 | ||
9068dba1 MT |
83 | def get_remote_location(self): |
84 | if not hasattr(self, "__remote_location"): | |
85 | remote_ip = self.get_remote_ip() | |
86 | ||
87 | self.__remote_location = self.geoip.get_location(remote_ip) | |
88 | ||
89 | return self.__remote_location | |
90 | ||
bd2723d4 MT |
91 | def get_argument_int(self, *args, **kwargs): |
92 | arg = self.get_argument(*args, **kwargs) | |
93 | ||
94 | if arg is None or arg == "": | |
95 | return | |
96 | ||
97 | try: | |
98 | return int(arg) | |
99 | except ValueError: | |
100 | raise tornado.web.HTTPError(400) | |
101 | ||
66862195 MT |
102 | def get_argument_date(self, arg, *args, **kwargs): |
103 | value = self.get_argument(arg, *args, **kwargs) | |
104 | if value is None: | |
105 | return | |
106 | ||
107 | try: | |
108 | return dateutil.parser.parse(value) | |
109 | except ValueError: | |
110 | raise tornado.web.HTTPError(400) | |
111 | ||
5cc10421 MT |
112 | def get_file(self, name): |
113 | try: | |
114 | file = self.request.files[name][0] | |
115 | ||
116 | return file["filename"], file["body"], file["content_type"] | |
117 | except KeyError: | |
118 | return None | |
119 | ||
66862195 MT |
120 | # Login stuff |
121 | ||
122 | def get_current_user(self): | |
123 | session_id = self.get_cookie("session_id") | |
124 | if not session_id: | |
125 | return | |
126 | ||
127 | # Get account from the session object | |
128 | account = self.backend.accounts.get_by_session(session_id, self.request.host) | |
129 | ||
130 | # If the account was not found or the session was not valid | |
131 | # any more, we will remove the cookie. | |
132 | if not account: | |
133 | self.clear_cookie("session_id") | |
134 | ||
135 | return account | |
136 | ||
a6dc0bad MT |
137 | @property |
138 | def backend(self): | |
139 | return self.application.backend | |
140 | ||
9068dba1 MT |
141 | @property |
142 | def db(self): | |
143 | return self.backend.db | |
144 | ||
940227cb MT |
145 | @property |
146 | def accounts(self): | |
a6dc0bad | 147 | return self.backend.accounts |
940227cb MT |
148 | |
149 | @property | |
9068dba1 MT |
150 | def downloads(self): |
151 | return self.backend.downloads | |
152 | ||
66862195 MT |
153 | @property |
154 | def fireinfo(self): | |
155 | return self.backend.fireinfo | |
156 | ||
9068dba1 MT |
157 | @property |
158 | def iuse(self): | |
159 | return self.backend.iuse | |
940227cb MT |
160 | |
161 | @property | |
162 | def mirrors(self): | |
9068dba1 MT |
163 | return self.backend.mirrors |
164 | ||
165 | @property | |
166 | def netboot(self): | |
167 | return self.backend.netboot | |
940227cb | 168 | |
940227cb MT |
169 | @property |
170 | def releases(self): | |
9068dba1 | 171 | return self.backend.releases |
940227cb MT |
172 | |
173 | @property | |
9068dba1 MT |
174 | def geoip(self): |
175 | return self.backend.geoip | |
940227cb MT |
176 | |
177 | @property | |
66862195 MT |
178 | def talk(self): |
179 | return self.backend.talk | |
940227cb | 180 | |
66862195 | 181 | |
3403dc5e MT |
182 | class NotFoundHandler(BaseHandler): |
183 | def prepare(self): | |
184 | # Raises 404 as soon as it is called | |
185 | raise tornado.web.HTTPError(404) | |
186 | ||
3403dc5e | 187 | |
37ed7c3c MT |
188 | class ErrorHandler(BaseHandler): |
189 | """ | |
190 | Raises any error we want | |
191 | """ | |
192 | def get(self, code): | |
193 | try: | |
194 | code = int(code) | |
195 | except: | |
196 | raise tornado.web.HTTPError(400) | |
197 | ||
198 | raise tornado.web.HTTPError(code) | |
baa693a3 MT |
199 | |
200 | ||
201 | class BlockedHandler(BaseHandler): | |
202 | def get(self): | |
203 | # 403 - Forbidden | |
204 | self.set_status(403) | |
205 | ||
206 | self.render("static/blocked.html", address=self.get_remote_ip()) |