#!/usr/bin/python
-import datetime
-import httplib
-import mimetypes
-import operator
+#import httplib
+#import logging
+#import markdown2
import os
-import simplejson
-import stat
-import sqlite3
-import time
-import urlparse
-
-import tornado.httpclient
-import tornado.locale
+#import random
+#import re
+#import socket
+#import time
+#import tornado.database
+#import tornado.locale
import tornado.web
+#import unicodedata
-from banners import banners
-from helpers import size, Item
-from info import info
-from mirrors import mirrors
-from news import news
-from releases import releases
-from torrent import tracker, bencode, bdecode, decode_hex
-
-import builds
-import menu
-#import uriel
-
-class BaseHandler(tornado.web.RequestHandler):
- def get_user_locale(self):
- uri = self.request.uri.split("/")
- if len(uri) > 1:
- for lang in tornado.locale.get_supported_locales(None):
- if lang[:2] == uri[1]:
- return tornado.locale.get(lang)
-
- @property
- def render_args(self):
- return {
- "banner" : banners.get(),
- "lang" : self.locale.code[:2],
- "langs" : [l[:2] for l in tornado.locale.get_supported_locales(None)],
- "lang_link" : self.lang_link,
- "link" : self.link,
- "title" : "no title given",
- "server" : self.request.host.replace("ipfire", "<span>ipfire</span>"),
- "uri" : self.request.uri,
- "year" : time.strftime("%Y"),
- }
-
- def render(self, *args, **kwargs):
- nargs = self.render_args
- nargs.update(kwargs)
- nargs["hostname"] = self.request.host
- tornado.web.RequestHandler.render(self, *args, **nargs)
+import backend
- def link(self, s):
- return "/%s/%s" % (self.locale.code[:2], s)
-
- def lang_link(self, lang):
- return "/%s/%s" % (lang, self.request.uri[4:])
-
- def get_error_html(self, status_code, **kwargs):
- if status_code in (404, 500):
- render_args = self.render_args
- render_args.update({
- "code" : status_code,
- "exception" : kwargs.get("exception", None),
- "message" : httplib.responses[status_code],
- })
- return self.render_string("error-%s.html" % status_code, **render_args)
- else:
- return tornado.web.RequestHandler.get_error_html(self, status_code, **kwargs)
+from handlers_admin import *
+from handlers_base import *
+from handlers_boot import *
+from handlers_download import *
+from handlers_iuse import *
+from handlers_mirrors import *
+from handlers_news import *
+from handlers_nopaste import *
+from handlers_planet import *
+from handlers_rss import *
+from handlers_stasy import *
+from handlers_tracker import *
+from handlers_wishlist import *
- @property
- def hash_db(self):
- return self.application.hash_db
-
-class MainHandler(BaseHandler):
- def get(self):
- lang = self.locale.code[:2]
- self.redirect("/%s/index" % (lang))
+class RootHandler(BaseHandler):
+ """
+ This handler redirects any request directly to /.
+ It can be used to be compatible with some ancient index urls.
+ """
+ def get(self, *args):
+ self.redirect("/")
-class DownloadHandler(BaseHandler):
- def get(self):
- self.render("downloads.html", release=releases.latest)
+class LangCompatHandler(BaseHandler):
+ """
+ Redirect links in the old format to current site:
-class DownloadAllHandler(BaseHandler):
- def get(self):
- self.render("downloads-all.html", releases=releases)
+ E.g. /en/index -> /index
+ """
+ def get(self, lang, page):
+ self.redirect("/%s" % page)
-class DownloadDevelopmentHandler(BaseHandler):
- def get(self):
- self.render("downloads-development.html", releases=releases)
-
-
-class DownloadTorrentHandler(BaseHandler):
- tracker_url = "http://tracker.ipfire.org:6969/stats?format=txt&mode=tpbs"
+class IndexHandler(BaseHandler):
+ rss_url = "/news.rss"
- @tornado.web.asynchronous
+ """
+ This handler displays the welcome page.
+ """
def get(self):
- http = tornado.httpclient.AsyncHTTPClient()
- http.fetch(self.tracker_url, callback=self.async_callback(self.on_response))
+ # Get a list of the most recent news items and put them on the page.
+ latest_news = self.news.get_latest(limit=1, locale=self.locale)
- def on_response(self, response):
- torrents = releases.torrents
- hashes = {}
- if response.code == 200:
- for line in response.body.split("\n"):
- if not line: continue
- hash, seeds, peers = line.split(":")
- hash.lower()
- hashes[hash] = {
- "peers" : peers,
- "seeds" : seeds,
- }
+ # Get the latest release.
+ latest_release = self.releases.get_latest()
- self.render("downloads-torrents.html",
- hashes=hashes,
- releases=torrents,
- request_time=response.request_time,
- tracker=urlparse.urlparse(response.request.url).netloc)
-
-
-class DownloadMirrorHandler(BaseHandler):
- def get(self):
- self.render("downloads-mirrors.html", mirrors=mirrors)
+ return self.render("index.html", latest_news=latest_news,
+ latest_release=latest_release)
class StaticHandler(BaseHandler):
+ """
+ This handler shows the files that are in plain html format.
+ """
@property
def static_path(self):
return os.path.join(self.application.settings["template_path"], "static")
@property
def static_files(self):
- ret = []
- for filename in os.listdir(self.static_path):
- if filename.endswith(".html"):
- ret.append(filename)
- return ret
+ for dir, subdirs, files in os.walk(self.static_path):
+ dir = dir[len(self.static_path) + 1:]
+ for file in files:
+ if not file.endswith(".html"):
+ continue
+ yield os.path.join(dir, file)
def get(self, name=None):
name = "%s.html" % name
if not name in self.static_files:
raise tornado.web.HTTPError(404)
- self.render("static/%s" % name)
-
-
-class IndexHandler(BaseHandler):
- def get(self):
- self.render("index.html", news=news)
-
-
-class NewsHandler(BaseHandler):
- def get(self):
- self.render("news.html", news=news)
-
-
-class BuildHandler(BaseHandler):
- def prepare(self):
- self.builds = {
- "<12h" : [],
- ">12h" : [],
- ">24h" : [],
- }
-
- for build in builds.find():
- if (time.time() - float(build.get("date"))) < 12*60*60:
- self.builds["<12h"].append(build)
- elif (time.time() - float(build.get("date"))) < 24*60*60:
- self.builds[">12h"].append(build)
- else:
- self.builds[">24h"].append(build)
-
- for l in self.builds.values():
- l.sort()
-
- def get(self):
- self.render("builds.html", builds=self.builds)
-
-
-class UrielBaseHandler(BaseHandler):
- #db = uriel.Database()
- pass
-
-class UrielHandler(UrielBaseHandler):
- def get(self):
- pass
-
-
-class SourceHandler(BaseHandler):
- def get(self):
- source_path = "/srv/sources"
- fileobjects = []
-
- for dir, subdirs, files in os.walk(source_path):
- if not files:
- continue
- for file in files:
- if file in [f["name"] for f in fileobjects]:
- continue
-
- hash = self.hash_db.get_hash(os.path.join(dir, file))
-
- if not hash:
- hash = "0000000000000000000000000000000000000000"
-
- fileobjects.append({
- "dir" : dir[len(source_path)+1:],
- "name" : file,
- "hash" : hash,
- "size" : size(os.path.getsize(os.path.join(source_path, dir, file))),
- })
-
- fileobjects.sort(key=operator.itemgetter("name"))
-
- self.render("sources.html", files=fileobjects)
-
-
-class SourceDownloadHandler(BaseHandler):
- def head(self, path):
- self.get(path, include_body=False)
-
- def get(self, path, include_body=True):
- source_path = "/srv/sources"
-
- path = os.path.abspath(os.path.join(source_path, path[1:]))
-
- if not path.startswith(source_path):
- raise tornado.web.HTTPError(403)
- if not os.path.exists(path):
- raise tornado.web.HTTPError(404)
-
- stat_result = os.stat(path)
- modified = datetime.datetime.fromtimestamp(stat_result[stat.ST_MTIME])
-
- self.set_header("Last-Modified", modified)
- self.set_header("Content-Length", stat_result[stat.ST_SIZE])
-
- mime_type, encoding = mimetypes.guess_type(path)
- if mime_type:
- self.set_header("Content-Type", mime_type)
-
- hash = self.hash_db.get_hash(path)
- if hash:
- self.set_header("X-Hash-Sha1", "%s" % hash)
-
- if not include_body:
- return
- file = open(path, "r")
- try:
- self.write(file.read())
- finally:
- file.close()
-
-
-class DownloadFileHandler(BaseHandler):
- def get(self, path):
- for mirror in mirrors.with_file(path):
- if not mirror.reachable:
- continue
-
- self.redirect(mirror.url + path)
- return
-
- raise tornado.web.HTTPError(404)
-
- def get_error_html(self, status_code, **kwargs):
- return tornado.web.RequestHandler.get_error_html(self, status_code, **kwargs)
-
-
-class RSSHandler(BaseHandler):
- def get(self, lang):
- items = []
- for item in news.get(15):
- item = Item(**item.args.copy())
- for attr in ("subject", "content"):
- if type(item[attr]) == type({}):
- item[attr] = item[attr][lang]
- items.append(item)
-
- self.set_header("Content-Type", "application/rss+xml")
- self.render("rss.xml", items=items, lang=lang)
-
-
-class TrackerBaseHandler(tornado.web.RequestHandler):
- def get_hexencoded_argument(self, name, all=False):
- try:
- arguments = self.request.arguments[name]
- except KeyError:
- return None
-
- arguments_new = []
- for argument in arguments:
- arguments_new.append(decode_hex(argument))
-
- arguments = arguments_new
-
- if all:
- return arguments
-
- return arguments[0]
-
- def send_tracker_error(self, error_message):
- self.write(bencode({"failure reason" : error_message }))
- self.finish()
-
-class TrackerAnnounceHandler(TrackerBaseHandler):
- def get(self):
- self.set_header("Content-Type", "text/plain")
-
- info_hash = self.get_hexencoded_argument("info_hash")
- if not info_hash:
- self.send_tracker_error("Your client forgot to send your torrent's info_hash.")
- return
-
- peer = {
- "id" : self.get_hexencoded_argument("peer_id"),
- "ip" : self.get_argument("ip", None),
- "port" : self.get_argument("port", None),
- "downloaded" : self.get_argument("downloaded", 0),
- "uploaded" : self.get_argument("uploaded", 0),
- "left" : self.get_argument("left", 0),
- }
-
- event = self.get_argument("event", "")
- if not event in ("started", "stopped", "completed", ""):
- self.send_tracker_error("Got unknown event")
- return
-
- if peer["ip"]:
- if peer["ip"].startswith("10.") or \
- peer["ip"].startswith("172.") or \
- peer["ip"].startswith("192.168."):
- peer["ip"] = self.request.remote_ip
-
- if peer["port"]:
- peer["port"] = int(peer["port"])
-
- if peer["port"] < 0 or peer["port"] > 65535:
- self.send_tracker_error("Port number is not in valid range")
- return
-
- eventhandlers = {
- "started" : tracker.event_started,
- "stopped" : tracker.event_stopped,
- "completed" : tracker.event_completed,
- }
-
- if event:
- eventhandlers[event](info_hash, peer["id"])
-
- tracker.update(hash=info_hash, **peer)
-
- no_peer_id = self.get_argument("no_peer_id", False)
- numwant = self.get_argument("numwant", tracker.numwant)
-
- self.write(bencode({
- "tracker id" : tracker.id,
- "interval" : tracker.interval,
- "min interval" : tracker.min_interval,
- "peers" : tracker.get_peers(info_hash, limit=numwant,
- random=True, no_peer_id=no_peer_id),
- "complete" : tracker.complete(info_hash),
- "incomplete" : tracker.incomplete(info_hash),
- }))
- self.finish()
-
-
-class TrackerScrapeHandler(TrackerBaseHandler):
- def get(self):
- info_hashes = self.get_hexencoded_argument("info_hash", all=True)
-
- self.write(bencode(tracker.scrape(hashes=info_hashes)))
- self.finish()
+ self.render("static/%s" % name, lang=self.locale.code[:2])