]> git.ipfire.org Git - ipfire.org.git/blame - src/web/__init__.py
wiki: Add preview for editing pages
[ipfire.org.git] / src / web / __init__.py
CommitLineData
81675874 1#/usr/bin/python
2
feb02477 3import logging
401827c2 4import itertools
81675874 5import os.path
c01ad253 6import phonenumbers
e96e445b 7import phonenumbers.geocoder
81675874 8import tornado.locale
a49b5422 9import tornado.options
81675874 10import tornado.web
11
a95c2f97 12import ipfire
574a88c7 13import ipfire.countries
feb02477 14
11347e46 15from .handlers import *
81675874 16
08df6527 17from . import auth
12e5de7e 18from . import blog
f301d952 19from . import boot
c7bcb9ca 20from . import donate
e77cd04c 21from . import download
96c9bb79 22from . import fireinfo
699a0911 23from . import iuse
f5b01fc2 24from . import location
95483f04 25from . import mirrors
5613b94b 26from . import newsletter
a41085fb 27from . import nopaste
03706893 28from . import people
df6180a5 29from . import ui_modules
181d08f3 30from . import wiki
12e5de7e 31
81675874 32class Application(tornado.web.Application):
3e7c6ccd
MT
33 def __init__(self, config, **kwargs):
34 # Initialize backend
a95c2f97 35 self.backend = ipfire.Backend(config)
a6dc0bad 36
9ed02e3b
MT
37 settings = {
38 # Do not compress responses
39 "gzip" : False,
40
41 # Enable XSRF cookies
42 "xsrf_cookies" : True,
43
44 # Login
45 "login_url" : "/login",
46
47 # Setup directory structure
48 "static_path" : self.backend.config.get("global", "static_dir"),
49 "template_path" : self.backend.config.get("global", "templates_dir"),
50
eabe6b8d 51 # UI Methods
9ed02e3b 52 "ui_methods" : {
574a88c7 53 "format_country_name" : self.format_country_name,
6eddfb50 54 "format_language_name" : self.format_language_name,
e96e445b
MT
55 "format_month_name" : self.format_month_name,
56 "format_phone_number" : self.format_phone_number,
57 "format_phone_number_to_e164" : self.format_phone_number_to_e164,
58 "format_phone_number_location" : self.format_phone_number_location,
59 "grouper" : grouper,
cc3b928d 60 },
eabe6b8d
MT
61
62 # UI Modules
9ed02e3b 63 "ui_modules" : {
f5b01fc2 64 # Blog
7e64f6a3
MT
65 "BlogHistoryNavigation": blog.HistoryNavigationModule,
66 "BlogList" : blog.ListModule,
f91dfcc7 67 "BlogPost" : blog.PostModule,
8a897d25 68 "BlogPosts" : blog.PostsModule,
f91dfcc7 69
93feb275
MT
70 # Boot
71 "BootMenuConfig" : boot.MenuConfigModule,
72 "BootMenuHeader" : boot.MenuHeaderModule,
73 "BootMenuSeparator" : boot.MenuSeparatorModule,
74
eabe6b8d 75 # People
dbb0c109
MT
76 "AccountsList" : people.AccountsListModule,
77 "CDR" : people.CDRModule,
78 "Channels" : people.ChannelsModule,
68ece434 79 "MOS" : people.MOSModule,
b5e2077f 80 "Password" : people.PasswordModule,
dbb0c109 81 "Registrations" : people.RegistrationsModule,
7afd64bb 82 "SIPStatus" : people.SIPStatusModule,
917434b8 83
e1814f16
MT
84 # Nopaste
85 "Code" : nopaste.CodeModule,
86
23f0179e 87 # Fireinfo
96c9bb79 88 "FireinfoDeviceTable" : fireinfo.DeviceTableModule,
eabe6b8d
MT
89 "FireinfoDeviceAndGroupsTable"
90 : fireinfo.DeviceAndGroupsTableModule,
91
6ac7e934 92 # Wiki
c21ffadb 93 "WikiDiff" : wiki.WikiDiffModule,
6ac7e934 94 "WikiNavbar" : wiki.WikiNavbarModule,
f9db574a 95 "WikiList" : wiki.WikiListModule,
6ac7e934 96
eabe6b8d
MT
97 # Misc
98 "Map" : ui_modules.MapModule,
99 "ProgressBar" : ui_modules.ProgressBarModule,
81675874 100 },
3403dc5e
MT
101
102 # Call this when a page wasn't found
b22bc8e8 103 "default_handler_class" : base.NotFoundHandler,
9ed02e3b 104 }
9068dba1 105 settings.update(kwargs)
5cf160e0 106
ae0228e1
MT
107 tornado.web.Application.__init__(self, **settings)
108
66862195 109 authentication_handlers = [
08df6527
MT
110 (r"/login", auth.LoginHandler),
111 (r"/logout", auth.LogoutHandler),
66862195
MT
112 ]
113
399506a8 114 self.add_handlers(r"(dev|www)\.ipfire\.org", [
940227cb
MT
115 # Entry site that lead the user to index
116 (r"/", IndexHandler),
940227cb 117
81675874 118 # Download sites
60b0917c 119 (r"/downloads", tornado.web.RedirectHandler, { "url" : "/download" }),
e77cd04c
MT
120 (r"/download", download.IndexHandler),
121 (r"/download/([0-9a-z\-\.]+)", download.ReleaseHandler),
940227cb 122
e64ce07e 123 # Donate
c7bcb9ca
MT
124 (r"/donate", donate.DonateHandler),
125 (r"/donate/thank-you", donate.ThankYouHandler),
126 (r"/donate/error", donate.ErrorHandler),
e64ce07e 127 (r"/donation", tornado.web.RedirectHandler, { "url" : "/donate" }),
8d48f4ef 128
5613b94b
MT
129 # Newsletter
130 (r"/newsletter/subscribe", newsletter.SubscribeHandler),
131
de683d7c 132 # RSS feed
f0714277 133 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
7f9dbcc0
MT
134
135 # Redirect news articles to blog
d76ec66e 136 (r"/news/(.*)", handlers.NewsHandler),
de683d7c 137
45592df5 138 # Static Pages
84151dbf 139 (r"/chat", StaticHandler, { "template" : "chat.html" }),
45592df5 140 (r"/features", StaticHandler, { "template" : "features.html" }),
45592df5 141 (r"/legal", StaticHandler, { "template" : "legal.html" }),
00026d8b 142 (r"/support", StaticHandler, { "template" : "support.html" }),
45592df5 143
14cd4fa8
MT
144 # Handle old pages that have moved elsewhere
145 (r"/imprint", tornado.web.RedirectHandler, { "url" : "/legal" }),
3808b871 146 (r"/(de|en)/(.*)", LangCompatHandler),
37ed7c3c
MT
147
148 # Export arbitrary error pages
b22bc8e8 149 (r"/error/([45][0-9]{2})", base.ErrorHandler),
baa693a3
MT
150
151 # Block page
b22bc8e8 152 (r"/blocked", base.BlockedHandler),
940227cb
MT
153 ])
154
12e5de7e
MT
155 # blog.ipfire.org
156 self.add_handlers(r"blog(\.dev)?\.ipfire\.org", [
8a897d25 157 (r"/", blog.IndexHandler),
cfc0823a 158 (r"/authors/(\w+)", blog.AuthorHandler),
541c952b 159 (r"/compose", blog.ComposeHandler),
0b342a05 160 (r"/drafts", blog.DraftsHandler),
d17a2624 161 (r"/post/([0-9a-z\-\._]+)", blog.PostHandler),
914238a5 162 (r"/post/([0-9a-z\-\._]+)/delete", blog.DeleteHandler),
d17a2624
MT
163 (r"/post/([0-9a-z\-\._]+)/edit", blog.EditHandler),
164 (r"/post/([0-9a-z\-\._]+)/publish", blog.PublishHandler),
e6b18dce 165 (r"/search", blog.SearchHandler),
8d7487d2 166 (r"/tags/([0-9a-z\-\.]+)", blog.TagHandler),
7e64f6a3 167 (r"/years/([0-9]+)", blog.YearHandler),
f0714277
MT
168
169 # RSS Feed
170 (r"/feed.xml", blog.FeedHandler),
08df6527 171 ] + authentication_handlers)
12e5de7e 172
940227cb 173 # downloads.ipfire.org
80594ae3 174 self.add_handlers(r"downloads?(\.dev)?\.ipfire\.org", [
ed8116c7 175 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/" }),
5cf65b4f 176 (r"/release/(.*)", download.ReleaseRedirectHandler),
ed8116c7 177 (r"/(.*)", download.FileHandler),
54af860e 178 ])
940227cb
MT
179
180 # mirrors.ipfire.org
8fceca0a 181 self.add_handlers(r"mirrors(\.dev)?\.ipfire\.org", [
95483f04
MT
182 (r"/", mirrors.IndexHandler),
183 (r"/mirrors/(.*)", mirrors.MirrorHandler),
3808b871 184 ])
940227cb 185
d0d074e0 186 # planet.ipfire.org
7cad1818 187 self.add_handlers(r"planet(\.dev)?\.ipfire\.org", [
3d4ce901 188 (r"/", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/" }),
d76ec66e
MT
189 (r"/post/([A-Za-z0-9_-]+)", handlers.PlanetPostHandler),
190 (r"/user/([a-z0-9_-]+)", handlers.PlanetUserHandler),
bcc3ed4d
MT
191
192 # RSS
f0714277 193 (r"/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
d76ec66e 194 (r"/user/([a-z0-9_-]+)/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
f0714277 195 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
3808b871 196 ])
d0d074e0 197
66862195 198 # fireinfo.ipfire.org
8fceca0a 199 self.add_handlers(r"fireinfo(\.dev)?\.ipfire\.org", [
96c9bb79 200 (r"/", fireinfo.IndexHandler),
8ab37e0b
MT
201
202 # Vendors
203 (r"/vendors", fireinfo.VendorsHandler),
204 (r"/vendors/(pci|usb)/([0-9a-f]{4})", fireinfo.VendorHandler),
66862195 205
1e3b2aad 206 # Driver
0cd21a36 207 (r"/drivers/(.*)", fireinfo.DriverDetail),
1e3b2aad 208
66862195 209 # Show profiles
96c9bb79 210 (r"/profile/random", fireinfo.RandomProfileHandler),
b84b407f 211 (r"/profile/([a-z0-9]{40})", fireinfo.ProfileHandler),
91a446f0 212
ed2e3c1f 213 # Stats
19518d6e 214 (r"/processors", fireinfo.ProcessorsHandler),
ed2e3c1f
MT
215 (r"/releases", fireinfo.ReleasesHandler),
216
19518d6e 217 # Send profiles
96c9bb79 218 (r"/send/([a-z0-9]+)", fireinfo.ProfileSendHandler),
3808b871 219 ])
5cf160e0 220
c37ec602 221 # i-use.ipfire.org
8fceca0a 222 self.add_handlers(r"i-use(\.dev)?\.ipfire\.org", [
e2f2865d 223 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/" }),
395c1ac0 224 (r"/profile/([a-f0-9]{40})/([0-9]+).png", iuse.ImageHandler),
c37ec602
MT
225 ])
226
8e2e1261
MT
227 # boot.ipfire.org
228 BOOT_STATIC_PATH = os.path.join(self.settings["static_path"], "netboot")
8fceca0a 229 self.add_handlers(r"boot(\.dev)?\.ipfire\.org", [
f301d952 230 (r"/", tornado.web.RedirectHandler, { "url" : "https://wiki.ipfire.org/installation/pxe" }),
8e2e1261
MT
231
232 # Configurations
f301d952
MT
233 (r"/premenu.cfg", boot.PremenuCfgHandler),
234 (r"/menu.gpxe", boot.MenuGPXEHandler),
235 (r"/menu.cfg", boot.MenuCfgHandler),
8e2e1261
MT
236
237 # Static files
37b5c0cf 238 (r"/(boot\.png|pxelinux\.0|menu\.c32|vesamenu\.c32)",
8e2e1261
MT
239 tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
240 ])
241
60024cc8 242 # nopaste.ipfire.org
8fceca0a 243 self.add_handlers(r"nopaste(\.dev)?\.ipfire\.org", [
a41085fb
MT
244 (r"/", nopaste.CreateHandler),
245 (r"/raw/(.*)", nopaste.RawHandler),
246 (r"/view/(.*)", nopaste.ViewHandler),
3808b871 247 ] + authentication_handlers)
60024cc8 248
f5b01fc2
MT
249 # location.ipfire.org
250 self.add_handlers(r"location(\.dev)?\.ipfire\.org", [
251 (r"/", location.IndexHandler),
2517822e 252 (r"/lookup/(.+)/blacklists", location.BlacklistsHandler),
f5b01fc2
MT
253 (r"/lookup/(.+)", location.LookupHandler),
254 ])
255
9068dba1 256 # geoip.ipfire.org
8fceca0a 257 self.add_handlers(r"geoip(\.dev)?\.ipfire\.org", [
f5b01fc2 258 (r"/", tornado.web.RedirectHandler, { "url" : "https://location.ipfire.org/" }),
3808b871 259 ])
9068dba1 260
66862195
MT
261 # talk.ipfire.org
262 self.add_handlers(r"talk(\.dev)?\.ipfire\.org", [
786e9ca8
MT
263 (r"/", tornado.web.RedirectHandler, { "url" : "https://people.ipfire.org/" }),
264 ])
66862195 265
03706893
MT
266 # people.ipfire.org
267 self.add_handlers(r"people(\.dev)?\.ipfire\.org", [
786e9ca8 268 (r"/", people.IndexHandler),
d8a15b2e 269 (r"/activate/(\w+)/(\w+)", auth.ActivateHandler),
30aeccdb 270 (r"/conferences", people.ConferencesHandler),
f32dd17f 271 (r"/register", auth.RegisterHandler),
786e9ca8
MT
272 (r"/search", people.SearchHandler),
273 (r"/users", people.UsersHandler),
274 (r"/users/(\w+)", people.UserHandler),
03706893 275 (r"/users/(\w+)\.jpg", people.AvatarHandler),
68ece434 276 (r"/users/(\w+)/calls/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})", people.CallHandler),
bdaf6b46 277 (r"/users/(\w+)/calls(?:/(\d{4}-\d{2}-\d{2}))?", people.CallsHandler),
e96e445b 278 (r"/users/(\w+)/edit", people.UserEditHandler),
3ea97943 279 (r"/users/(\w+)/passwd", people.UserPasswdHandler),
f4672785 280 (r"/users/(\w+)/ssh-keys", people.SSHKeysIndexHandler),
44b75370
MT
281 (r"/users/(\w+)/ssh-keys/(SHA256\:.*)/delete", people.SSHKeysDeleteHandler),
282 (r"/users/(\w+)/ssh-keys/(SHA256\:.*)", people.SSHKeysDownloadHandler),
0d1fb712 283 (r"/users/(\w+)/ssh-keys/upload", people.SSHKeysUploadHandler),
e0daee8f 284 (r"/users/(\w+)/sip", people.SIPHandler),
786e9ca8 285 ] + authentication_handlers)
2cd9af74 286
181d08f3
MT
287 # wiki.ipfire.org
288 self.add_handlers(r"wiki(\.dev)?\.ipfire\.org",
289 authentication_handlers + [
290
f2cfd873 291 # Actions
40cb87a4 292 (r"([A-Za-z0-9\-_\/]+)?/_edit", wiki.ActionEditHandler),
2901b734 293 (r"([A-Za-z0-9\-_\/]+)?/_render", wiki.ActionRenderHandler),
9db2e89f 294 (r"([A-Za-z0-9\-_\/]+)?/_(watch|unwatch)", wiki.ActionWatchHandler),
f2cfd873
MT
295 (r"/actions/upload", wiki.ActionUploadHandler),
296
f9db574a
MT
297 # Handlers
298 (r"/recent\-changes", wiki.RecentChangesHandler),
181d08f3 299 (r"/search", wiki.SearchHandler),
2f23c558 300 (r"/watchlist", wiki.WatchlistHandler),
f9db574a 301
f2cfd873 302 # Media
3b33319e 303 (r"([A-Za-z0-9\-_\/]+)?/_files", wiki.FilesHandler),
f2cfd873
MT
304 (r"((?!/static)(?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))$", wiki.FileHandler),
305
f9db574a 306 # Render pages
181d08f3
MT
307 (r"([A-Za-z0-9\-_\/]+)?", wiki.PageHandler),
308 ])
309
ae0228e1 310 # ipfire.org
45592df5 311 self.add_handlers(r"ipfire\.org", [
ba43a892 312 (r".*", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org" })
5cf160e0 313 ])
3add293a 314
feb02477
MT
315 logging.info("Successfully initialied application")
316
574a88c7
MT
317 def format_country_name(self, handler, country_code):
318 return ipfire.countries.get_name(country_code)
319
6eddfb50
MT
320 def format_language_name(self, handler, language):
321 _ = handler.locale.translate
322
323 if language == "de":
324 return _("German")
325 elif language == "en":
326 return _("English")
327 elif language == "es":
328 return _("Spanish")
329 elif language == "fr":
330 return _("French")
331 elif language == "it":
332 return _("Italian")
333 elif language == "nl":
334 return _("Dutch")
335 elif language == "pl":
336 return _("Polish")
337 elif language == "pt":
338 return _("Portuguese")
339 elif language == "ru":
340 return _("Russian")
341 elif language == "tr":
342 return _("Turkish")
343
344 return language
345
cc3b928d
MT
346 def format_month_name(self, handler, month):
347 _ = handler.locale.translate
348
349 if month == 1:
350 return _("January")
351 elif month == 2:
352 return _("February")
353 elif month == 3:
354 return _("March")
355 elif month == 4:
356 return _("April")
357 elif month == 5:
358 return _("May")
359 elif month == 6:
360 return _("June")
361 elif month == 7:
362 return _("July")
363 elif month == 8:
364 return _("August")
365 elif month == 9:
366 return _("September")
367 elif month == 10:
368 return _("October")
369 elif month == 11:
370 return _("November")
371 elif month == 12:
372 return _("December")
373
374 return month
401827c2 375
e96e445b
MT
376 def format_phone_number(self, handler, number):
377 if not isinstance(number, phonenumbers.PhoneNumber):
378 try:
01e73b0e 379 number = phonenumbers.parse(number, None)
e96e445b
MT
380 except phonenumbers.phonenumberutil.NumberParseException:
381 return number
c01ad253
MT
382
383 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
384
e96e445b
MT
385 def format_phone_number_to_e164(self, handler, number):
386 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
387
388 def format_phone_number_location(self, handler, number):
389 s = [
390 phonenumbers.geocoder.description_for_number(number, handler.locale.code),
391 phonenumbers.region_code_for_number(number),
392 ]
393
394 return ", ".join((e for e in s if e))
395
401827c2
MT
396
397def grouper(handler, iterator, n):
398 """
399 Returns groups of n from the iterator
400 """
401 i = iter(iterator)
402
403 while True:
404 ret = list(itertools.islice(i, 0, n))
405 if not ret:
406 break
407
408 yield ret