eb31d1d778c6256198a64e03a09ce7e989a3bd7c
[people/shoehn/ipfire.org.git] / webapp / __init__.py
1 #/usr/bin/python
2
3 import logging
4 import multiprocessing
5 import os.path
6 import simplejson
7 import tornado.httpserver
8 import tornado.locale
9 import tornado.web
10
11 from tornado.options import options
12
13 import backend
14
15 from handlers import *
16 from ui_modules import *
17
18 BASEDIR = os.path.join(os.path.dirname(__file__), "..")
19
20 # Load translations.
21 tornado.locale.load_gettext_translations(os.path.join(BASEDIR, "translations"), "webapp")
22
23 class Application(tornado.web.Application):
24         def __init__(self, **kwargs):
25                 self.__backend = None
26
27                 settings = dict(
28                         cookie_secret = "aXBmaXJlY29va2llc2VjcmV0Cg==",
29                         debug = options.debug,
30                         gzip = True,
31                         login_url = "/login",
32                         template_path = os.path.join(BASEDIR, "templates"),
33                         ui_methods = {
34                                 "format_month_name" : self.format_month_name,
35                         },
36                         ui_modules = {
37                                 "Advertisement"        : AdvertisementModule,
38                                 "DonationBox"          : DonationBoxModule,
39                                 "DonationButton"       : DonationButtonModule,
40                                 "DonationInputBox"     : DonationInputBoxModule,
41                                 "DownloadButton"       : DownloadButtonModule,
42                                 "LanguageName"         : LanguageNameModule,
43                                 "Map"                  : MapModule,
44                                 "Menu"                 : MenuModule,
45                                 "MirrorItem"           : MirrorItemModule,
46                                 "MirrorsTable"         : MirrorsTableModule,
47                                 "NetBootMenuConfig"    : NetBootMenuConfigModule,
48                                 "NetBootMenuHeader"    : NetBootMenuHeaderModule,
49                                 "NetBootMenuSeparator" : NetBootMenuSeparatorModule,
50                                 "NewsItem"             : NewsItemModule,
51                                 "NewsLine"             : NewsLineModule,
52                                 "NewsTable"            : NewsTableModule,
53                                 "NewsYearNavigation"   : NewsYearNavigationModule,
54                                 "PlanetAuthorBox"      : PlanetAuthorBoxModule,
55                                 "PlanetEntry"          : PlanetEntryModule,
56                                 "PlanetSearchBox"      : PlanetSearchBoxModule,
57                                 "ProgressBar"          : ProgressBarModule,
58                                 "ReleaseItem"          : ReleaseItemModule,
59                                 "SidebarBanner"        : SidebarBannerModule,
60                                 "SidebarRelease"       : SidebarReleaseModule,
61                                 "FireinfoDeviceTable"     : FireinfoDeviceTableModule,
62                                 "FireinfoDeviceAndGroupsTable" : FireinfoDeviceAndGroupsTableModule,
63                                 "FireinfoGeoTable"        : FireinfoGeoTableModule,
64                                 "TalkCallLog"          : TalkCallLogModule,
65                                 "TalkLines"            : TalkLinesModule,
66                                 "TalkOngoingCalls"     : TalkOngoingCallsModule,
67                                 "TrackerPeerList"      : TrackerPeerListModule,
68                                 "Wish"                 : WishModule,
69                                 "Wishlist"             : WishlistModule,
70                                 "WishlistItems"        : WishlistItemsModule,
71                         },
72                         xsrf_cookies = True,
73                 )
74                 settings.update(kwargs)
75
76                 tornado.web.Application.__init__(self, **settings)
77
78                 self.settings["static_path"] = static_path = os.path.join(BASEDIR, "static")
79                 static_handlers = [
80                         (r"/static/(.*)", tornado.web.StaticFileHandler, dict(path = static_path)),
81                         (r"/(favicon\.ico)", tornado.web.StaticFileHandler, dict(path = static_path)),
82                         (r"/(robots\.txt)", tornado.web.StaticFileHandler, dict(path = static_path)),
83                 ]
84
85                 authentication_handlers = [
86                         (r"/login", LoginHandler),
87                         (r"/logout", LogoutHandler),
88                 ]
89
90                 self.add_handlers(r"(dev|www)\.ipfire\.(at|org)", [
91                         # Entry site that lead the user to index
92                         (r"/", IndexHandler),
93                         (r"/index\.?(s?html?)?", RootHandler),
94
95                         # Handle news items
96                         (r"/news", NewsIndexHandler),
97                         (r"/news/year/([0-9]*)", NewsYearHandler),
98                         (r"/news/(.*)", NewsItemHandler),
99
100                         # Download sites
101                         (r"/download", DownloadHandler),
102                         (r"/downloads", tornado.web.RedirectHandler, { "url" : "/download" }),
103
104                         # Handle old pages that have moved elsewhere
105                         (r"/screenshots", tornado.web.RedirectHandler, { "url" : "/about" }),
106                         (r"/about", tornado.web.RedirectHandler, { "url" : "/features" }),
107                         (r"/features/.*", tornado.web.RedirectHandler, { "url" : "/features" }),
108                         (r"/getinvolved", tornado.web.RedirectHandler, { "url" : "/get-involved" }),
109
110                         # Donate
111                         (r"/donate", DonateHandler),
112                         (r"/donation", tornado.web.RedirectHandler, { "url" : "/donate" }),
113
114                         # RSS feed
115                         (r"/news.rss", RSSNewsHandler),
116
117                         # Redirection for bookmarks, etc.
118                         (r"/(de|en)/(.*)", LangCompatHandler)
119
120                 ] + static_handlers + [
121                         # Always the last rule
122                         (r"/(.*)", StaticHandler),
123                 ])
124
125                 # downloads.ipfire.org
126                 self.add_handlers(r"downloads?(\.dev)?\.ipfire\.org", [
127                         (r"/", DownloadsIndexHandler),
128                         (r"/latest", DownloadsLatestHandler),
129                         (r"/release/(\d)", DownloadsReleaseHandler),
130                         (r"/release/([\w\.\-]*)", DownloadsReleaseHandler),
131                         (r"/older", DownloadsOlderHandler),
132                         (r"/development", DownloadsDevelopmentHandler),
133                         (r"/mirrors", tornado.web.RedirectHandler, { "url" : "http://mirrors.ipfire.org/" }),
134                         (r"/source", tornado.web.RedirectHandler, { "url" : "http://source.ipfire.org/" }),
135                         (r"/download-splash", DownloadSplashHandler),
136                 ] + static_handlers + [
137                         (r"/(iso|torrent)/(.*)", DownloadCompatHandler),
138                         (r"/(.*)", DownloadFileHandler),
139                 ])
140
141                 # mirrors.ipfire.org
142                 self.add_handlers(r"mirrors(\.dev)?\.ipfire\.org", [
143                         (r"/", MirrorIndexHandler),
144                         (r"/mirror/(.*)", MirrorItemHandler),
145                         (r"/lists/pakfire2", MirrorListPakfire2Handler),
146                 ] + static_handlers)
147
148                 # planet.ipfire.org
149                 self.add_handlers(r"planet(\.dev)?\.ipfire\.org", [
150                         (r"/", PlanetMainHandler),
151                         (r"/hottest", PlanetHotEntriesHandler),
152                         (r"/post/([A-Za-z0-9_-]+)", PlanetPostingHandler),
153                         (r"/user/([a-z0-9_-]+)", PlanetUserHandler),
154                         (r"/search", PlanetSearchHandler),
155                         (r"/year/(\d+)", PlanetYearHandler),
156
157                         # RSS
158                         (r"/rss", RSSPlanetAllHandler),
159                         (r"/user/([a-z0-9_-]+)/rss", RSSPlanetUserHandler),
160                         (r"/news.rss", tornado.web.RedirectHandler, { "url" : "/rss" }),
161                 ] + static_handlers)
162
163                 # fireinfo.ipfire.org
164                 self.add_handlers(r"fireinfo(\.dev)?\.ipfire\.org", [
165                         (r"/", FireinfoIndexHandler),
166                         (r"/device/driver/(.*)", FireinfoDeviceDriverDetail),
167                         (r"/device/vendors", FireinfoDeviceVendorsHandler),
168                         (r"/device/(pci|usb)/([0-9a-f]{4})", FireinfoDeviceVendorHandler),
169                         (r"/device/(pci|usb)/([0-9a-f]{4})/([0-9a-f]{4})", FireinfoDeviceModelHandler),
170
171                         # Show profiles
172                         (r"/profile/random", FireinfoRandomProfileHandler),
173                         (r"/profile/([a-z0-9]{40})", FireinfoProfileDetailHandler),
174
175                         # Send profiles.
176                         (r"/send/([a-z0-9]+)", FireinfoProfileSendHandler),
177
178                         # Stats handlers
179                         (r"/statistics", FireinfoStatsHandler),
180                         (r"/statistics/processors", FireinfoStatsProcessorsHandler),
181                         (r"/statistics/processors/(arm|x86)", FireinfoStatsProcessorDetailHandler),
182                         (r"/statistics/geo-locations", FireinfoStatsGeoHandler),
183                         (r"/statistics/languages", FireinfoStatsLanguagesHandler),
184                         (r"/statistics/memory", FireinfoStatsMemoryHandler),
185                         (r"/statistics/networking", FireinfoStatsNetworkingHandler),
186                         (r"/statistics/releases", FireinfoStatsReleasesHandler),
187                         (r"/statistics/virtualization", FireinfoStatsVirtualHandler),
188
189                         # Compat handlers
190                         (r"/stats", tornado.web.RedirectHandler, { "url" : "/statistics" }),
191                         (r"/stats/cpus", tornado.web.RedirectHandler, { "url" : "/statistics/processors" }),
192                         (r"/stats/geo", tornado.web.RedirectHandler, { "url" : "/statistics/geo-locations" }),
193                         (r"/stats/network", tornado.web.RedirectHandler, { "url" : "/statistics/networking" }),
194                         (r"/stats/oses", tornado.web.RedirectHandler, { "url" : "/statistics/releases" }),
195                         (r"/stats/virtual", tornado.web.RedirectHandler, { "url" : "/statistics/virtualization" }),
196                         (r"/vendor/(pci|usb)/([0-9a-f]{4})", FireinfoDeviceVendorCompatHandler),
197                         (r"/model/(pci|usb)/([0-9a-f]{4})/([0-9a-f]{4})", FireinfoDeviceModelCompatHandler),
198                 ] + static_handlers)
199
200                 # i-use.ipfire.org
201                 self.add_handlers(r"i-use(\.dev)?\.ipfire\.org", [
202                         (r"/profile/([a-f0-9]{40})/([0-9]+).png", IUseImage),
203                 ])
204
205                 # tracker.ipfire.org
206                 self.add_handlers(r"(torrent|tracker)(\.dev)?\.ipfire\.org", [
207                         (r"/", TrackerIndexHandler),
208                         (r"/announce.*", TrackerAnnounceHandler),
209                         (r"/scrape", TrackerScrapeHandler),
210                         (r"/torrent/([0-9a-f]+)", TrackerDetailHandler),
211                         (r"/([0-9a-f]{40})", TrackerDetailHandler),
212                         (r"/([0-9a-f]{40})/download", TrackerDownloadHandler),
213                 ] + static_handlers)
214
215                 # boot.ipfire.org
216                 BOOT_STATIC_PATH = os.path.join(self.settings["static_path"], "netboot")
217                 self.add_handlers(r"boot(\.dev)?\.ipfire\.org", [
218                         (r"/", tornado.web.RedirectHandler, { "url" : "http://www.ipfire.org/download" }),
219
220                         # Configurations
221                         (r"/menu.gpxe", MenuGPXEHandler),
222                         (r"/menu.cfg", MenuCfgHandler),
223
224                         # Static files
225                         (r"/(boot\.png|premenu\.cfg|pxelinux\.0|menu\.c32|vesamenu\.c32)",
226                                 tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
227                 ])
228
229                 # nopaste.ipfire.org
230                 self.add_handlers(r"nopaste(\.dev)?\.ipfire\.org", [
231                         (r"/", NopasteCreateHandler),
232                         (r"/raw/(.*)", NopasteRawHandler),
233                         (r"/view/(.*)", NopasteViewHandler),
234                 ] + authentication_handlers + static_handlers)
235
236                 # wishlist.ipfire.org
237                 self.add_handlers(r"wishlist(\.dev)?\.ipfire\.org", [
238                         (r"/", WishlistIndexHandler),
239                         (r"/closed", WishlistClosedHandler),
240                         (r"/wish/(.*)/donate", WishDonateHandler),
241                         (r"/wish/(.*)", WishHandler),
242                         (r"/terms", WishlistTermsHandler),
243                 ] + static_handlers)
244
245                 # geoip.ipfire.org
246                 self.add_handlers(r"geoip(\.dev)?\.ipfire\.org", [
247                         (r"/", GeoIPHandler),
248                 ] + static_handlers)
249
250                 # talk.ipfire.org
251                 self.add_handlers(r"talk(\.dev)?\.ipfire\.org", [
252                         (r"/", TalkIndexHandler),
253                         (r"/call/(\d+)", TalkInitiateCallHandler),
254                         (r"/conferences", TalkConferencesHandler),
255                         (r"/conferences/(\d+)/invite/(\d+)", TalkConferencesInviteHandler),
256                         (r"/diagnosis", TalkDiagnosisHandler),
257                         (r"/phonebook/(\w+)", TalkPhonebookAccountHandler),
258                         (r"/phonebook", TalkPhonebookHandler),
259                         (r"/profile", TalkProfileHandler),
260                 ] + authentication_handlers + static_handlers)
261
262                 # accounts.ipfire.org
263                 self.add_handlers(r"accounts(\.dev)?\.ipfire\.org", [
264                         (r"/avatar/(\w+)\.jpg", AccountsAvatarHandler),
265                 ] + static_handlers)
266
267                 # admin.ipfire.org
268                 self.add_handlers(r"admin(\.dev)?\.ipfire\.org", [
269                         (r"/", AdminIndexHandler),
270                         # Accounts
271                         (r"/accounts", AdminAccountsHandler),
272                         #(r"/accounts/delete/([0-9]+)", AdminAccountsDeleteHandler),
273                         #(r"/accounts/edit/([0-9]+)", AdminAccountsEditHandler),
274                         # Planet
275                         (r"/planet", AdminPlanetHandler),
276                         (r"/planet/compose", AdminPlanetComposeHandler),
277                         (r"/planet/edit/(.*)", AdminPlanetEditHandler),
278                         (r"/planet/publish/(.*)", AdminPlanetPublishHandler),
279                         # Mirrors
280                         (r"/mirrors", AdminMirrorsHandler),
281                         (r"/mirrors/create", AdminMirrorsCreateHandler),
282                         (r"/mirrors/delete/([0-9]+)", AdminMirrorsDeleteHandler),
283                         (r"/mirrors/edit/([0-9]+)", AdminMirrorsEditHandler),
284                         (r"/mirrors/details/([0-9]+)", AdminMirrorsDetailsHandler),
285                         (r"/mirrors/update", AdminMirrorsUpdateHandler),
286                         # Fireinfo
287                         (r"/fireinfo", AdminFireinfoHandler),
288                         # Downloads
289                         (r"/downloads", AdminDownloadsHandler),
290                         (r"/downloads/mirrors", AdminDownloadsMirrorsHandler),
291                         # API
292                         (r"/api/planet/render", AdminApiPlanetRenderMarkupHandler)
293                 ] + authentication_handlers + static_handlers)
294
295                 # ipfire.org
296                 self.add_handlers(r".*", [
297                         (r".*", tornado.web.RedirectHandler, { "url" : "http://www.ipfire.org" })
298                 ])
299
300                 logging.info("Successfully initialied application")
301
302                 self.__running = True
303
304         def __del__(self):
305                 logging.info("Shutting down application")
306
307         @property
308         def backend(self):
309                 if self.__backend is None:
310                         configfile = self.settings.get("configfile", None)
311                         if not configfile:
312                                 raise RuntimeException("Could not find configuration file")
313
314                         self.__backend = backend.Backend(configfile=configfile,
315                                 debug=self.settings.get("debug", False))
316
317                 return self.__backend
318
319         @property
320         def ioloop(self):
321                 return tornado.ioloop.IOLoop.instance()
322
323         def shutdown(self, *args):
324                 logging.debug("Caught shutdown signal")
325                 self.ioloop.stop()
326
327                 self.__running = False
328
329         def run(self, port=8001):
330                 logging.debug("Going to background")
331
332                 http_server = tornado.httpserver.HTTPServer(self, xheaders=True)
333
334                 num_processes = multiprocessing.cpu_count() / 2
335
336                 # If we are not running in debug mode, we can actually run multiple
337                 # frontends to get best performance out of our service.
338                 if not self.settings["debug"]:
339                         http_server.bind(port)
340                         http_server.start(num_processes=num_processes)
341                 else:
342                         http_server.listen(port)
343                 
344                 # All requests should be done after 30 seconds or they will be killed.
345                 self.ioloop.set_blocking_log_threshold(30)
346
347                 self.ioloop.start()
348
349         def reload(self):
350                 logging.debug("Caught reload signal")
351
352         def format_month_name(self, handler, month):
353                 _ = handler.locale.translate
354
355                 if month == 1:
356                         return _("January")
357                 elif month == 2:
358                         return _("February")
359                 elif month == 3:
360                         return _("March")
361                 elif month == 4:
362                         return _("April")
363                 elif month == 5:
364                         return _("May")
365                 elif month == 6:
366                         return _("June")
367                 elif month == 7:
368                         return _("July")
369                 elif month == 8:
370                         return _("August")
371                 elif month == 9:
372                         return _("September")
373                 elif month == 10:
374                         return _("October")
375                 elif month == 11:
376                         return _("November")
377                 elif month == 12:
378                         return _("December")
379
380                 return month