2012-12-19 12:00:12 +00:00
|
|
|
from flask import Flask, request, g, redirect, url_for, abort, render_template, send_from_directory, safe_join
|
2012-09-17 01:19:57 +00:00
|
|
|
from flaskext.babel import Babel
|
2013-01-16 11:23:33 +00:00
|
|
|
from flask.ext.cache import Cache
|
2012-06-03 01:06:09 +00:00
|
|
|
from docutils.core import publish_parts
|
2012-06-01 21:15:42 +00:00
|
|
|
import os.path
|
2012-06-01 23:15:41 +00:00
|
|
|
import os
|
2012-06-01 21:15:42 +00:00
|
|
|
|
2012-12-20 04:49:25 +00:00
|
|
|
|
|
|
|
###########
|
|
|
|
# Constants
|
|
|
|
|
2013-08-11 09:01:06 +00:00
|
|
|
CURRENT_I2P_VERSION = '0.9.7.1'
|
2012-12-17 21:59:41 +00:00
|
|
|
|
2012-12-19 04:51:36 +00:00
|
|
|
CANONICAL_DOMAIN = 'www.i2p2.de'
|
|
|
|
|
2013-02-03 03:12:31 +00:00
|
|
|
BLOG_POSTS_PER_FEED = 10
|
|
|
|
BLOG_POSTS_PER_PAGE = 10
|
2012-12-20 04:49:25 +00:00
|
|
|
MEETINGS_PER_PAGE = 20
|
|
|
|
|
2013-01-04 12:38:49 +00:00
|
|
|
SUPPORTED_LANGS = [
|
|
|
|
'en',
|
|
|
|
'es',
|
2013-08-23 12:49:49 +00:00
|
|
|
'zh_CN',
|
2013-01-04 12:38:49 +00:00
|
|
|
'de',
|
|
|
|
'fr',
|
2013-03-01 21:02:19 +00:00
|
|
|
# 'it',
|
|
|
|
# 'nl',
|
|
|
|
# 'ru',
|
2013-07-18 02:30:45 +00:00
|
|
|
'sv_SE',
|
2013-03-01 21:02:19 +00:00
|
|
|
# 'cs',
|
|
|
|
# 'ar',
|
|
|
|
# 'el',
|
2013-07-18 04:43:41 +00:00
|
|
|
'pt',
|
2013-01-04 12:38:49 +00:00
|
|
|
]
|
|
|
|
|
2013-07-14 07:02:24 +00:00
|
|
|
DEFAULT_GETTEXT_DOMAIN = 'priority'
|
|
|
|
GETTEXT_DOMAIN_MAPPING = {
|
|
|
|
'about': ['about'],
|
|
|
|
'blog': ['blog'],
|
|
|
|
'comparison': ['comparison'],
|
|
|
|
'docs': ['docs'],
|
|
|
|
'get-involved': ['get-involved'],
|
|
|
|
'misc': ['misc'],
|
|
|
|
'research': ['research'],
|
|
|
|
}
|
|
|
|
|
2012-06-01 21:15:42 +00:00
|
|
|
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages')
|
2012-06-01 23:15:41 +00:00
|
|
|
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
|
2012-06-03 01:06:09 +00:00
|
|
|
BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog')
|
2012-12-19 06:58:07 +00:00
|
|
|
MEETINGS_DIR = os.path.join(os.path.dirname(__file__), 'meetings/logs')
|
2013-01-04 12:38:49 +00:00
|
|
|
SITE_DIR = os.path.join(TEMPLATE_DIR, 'site')
|
2012-12-20 04:49:25 +00:00
|
|
|
MIRRORS_FILE = os.path.join(TEMPLATE_DIR, 'downloads/mirrors')
|
2013-08-11 13:05:05 +00:00
|
|
|
ANONBIB_CFG = os.path.join(TEMPLATE_DIR, 'papers/anonbib.cfg')
|
|
|
|
ANONBIB_FILE = os.path.join(TEMPLATE_DIR, 'papers/anonbib.bib')
|
2012-06-01 21:15:42 +00:00
|
|
|
|
2012-12-14 06:26:21 +00:00
|
|
|
|
2012-12-20 04:49:25 +00:00
|
|
|
###################
|
|
|
|
# Application setup
|
2012-12-05 01:21:34 +00:00
|
|
|
|
2013-04-25 03:49:55 +00:00
|
|
|
class MyFlask(Flask):
|
|
|
|
jinja_options = dict(Flask.jinja_options)
|
|
|
|
jinja_options.setdefault('extensions',
|
|
|
|
[]).append('i2p2www.extensions.HighlightExtension')
|
|
|
|
|
|
|
|
app = application = MyFlask('i2p2www', template_folder=TEMPLATE_DIR, static_url_path='/_static', static_folder=STATIC_DIR)
|
2012-06-01 21:15:42 +00:00
|
|
|
app.debug = bool(os.environ.get('APP_DEBUG', 'False'))
|
2013-07-14 07:02:24 +00:00
|
|
|
babel = Babel(app, default_domain='priority')
|
2013-01-16 11:23:33 +00:00
|
|
|
cache = Cache(app, config={
|
|
|
|
'CACHE_DEFAULT_TIMEOUT': 600,
|
|
|
|
#'CACHE_TYPE': '', # See http://packages.python.org/Flask-Cache/#configuring-flask-cache
|
|
|
|
})
|
2012-09-17 01:19:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
#################
|
|
|
|
# Babel selectors
|
|
|
|
|
|
|
|
@babel.localeselector
|
|
|
|
def get_locale():
|
|
|
|
# If the language is already set from the url, use that
|
|
|
|
if hasattr(g, 'lang'):
|
|
|
|
return g.lang
|
|
|
|
# otherwise try to guess the language from the user accept
|
|
|
|
# header the browser transmits. The best match wins.
|
2013-07-14 07:01:13 +00:00
|
|
|
return request.accept_languages.best_match(SUPPORTED_LANGS)
|
2012-06-01 21:15:42 +00:00
|
|
|
|
2013-07-14 07:02:24 +00:00
|
|
|
@babel.domainselector
|
|
|
|
def get_domains():
|
|
|
|
domains = []
|
|
|
|
frags = request.path.split('/', 2)
|
|
|
|
if len(frags) == 3:
|
|
|
|
path = frags[2]
|
|
|
|
for subpath in GETTEXT_DOMAIN_MAPPING:
|
|
|
|
if path.startswith(subpath):
|
|
|
|
domains.extend(GETTEXT_DOMAIN_MAPPING[subpath])
|
|
|
|
# Always end with the priority domain, as it contains
|
|
|
|
# various template strings and is likely to be the most
|
|
|
|
# up-to-date (in case of any common translation strings).
|
|
|
|
domains.append(DEFAULT_GETTEXT_DOMAIN)
|
|
|
|
return domains
|
|
|
|
|
2012-09-10 12:14:29 +00:00
|
|
|
|
|
|
|
##########################
|
|
|
|
# Hooks - helper functions
|
2012-06-01 23:36:38 +00:00
|
|
|
|
|
|
|
def after_this_request(f):
|
|
|
|
if not hasattr(g, 'after_request_callbacks'):
|
|
|
|
g.after_request_callbacks = []
|
|
|
|
g.after_request_callbacks.append(f)
|
|
|
|
return f
|
|
|
|
|
2011-10-05 21:35:41 +00:00
|
|
|
|
2012-09-10 12:14:29 +00:00
|
|
|
###########################
|
|
|
|
# Hooks - url preprocessing
|
2011-10-05 21:35:41 +00:00
|
|
|
|
|
|
|
@app.url_value_preprocessor
|
|
|
|
def pull_lang(endpoint, values):
|
|
|
|
if not values:
|
|
|
|
return
|
|
|
|
g.lang=values.pop('lang', None)
|
|
|
|
|
2012-06-03 01:06:09 +00:00
|
|
|
@app.url_defaults
|
|
|
|
def set_lang(endpoint, values):
|
|
|
|
if not values:
|
|
|
|
return
|
2012-09-17 21:31:08 +00:00
|
|
|
if endpoint == 'static':
|
|
|
|
# Static urls shouldn't have a lang flag
|
|
|
|
# (causes complete reload on lang change)
|
|
|
|
return
|
2012-06-03 01:06:09 +00:00
|
|
|
if 'lang' in values:
|
|
|
|
return
|
|
|
|
if hasattr(g, 'lang'):
|
|
|
|
values['lang'] = g.lang
|
|
|
|
|
2012-09-10 12:14:29 +00:00
|
|
|
|
|
|
|
########################
|
|
|
|
# Hooks - before request
|
|
|
|
|
|
|
|
# Detect and store chosen theme
|
2012-06-01 23:36:38 +00:00
|
|
|
@app.before_request
|
|
|
|
def detect_theme():
|
2012-09-10 23:11:13 +00:00
|
|
|
theme = 'duck'
|
2012-06-01 23:36:38 +00:00
|
|
|
if 'style' in request.cookies:
|
|
|
|
theme = request.cookies['style']
|
|
|
|
if 'theme' in request.args.keys():
|
|
|
|
theme = request.args['theme']
|
2012-12-21 05:15:42 +00:00
|
|
|
# TEMPORARY: enable external themes
|
|
|
|
# TODO: Remove this (and the corresponding lines in global/layout.html
|
|
|
|
if theme[:7] == 'http://':
|
|
|
|
g.exttheme = theme
|
|
|
|
theme = 'duck'
|
2013-01-21 14:38:50 +00:00
|
|
|
if not os.path.isfile(safe_join(safe_join(STATIC_DIR, 'styles'), '%s/desktop.css' % theme)):
|
2012-09-10 23:11:13 +00:00
|
|
|
theme = 'duck'
|
2012-06-01 23:36:38 +00:00
|
|
|
g.theme = theme
|
|
|
|
@after_this_request
|
|
|
|
def remember_theme(resp):
|
2012-09-10 23:11:13 +00:00
|
|
|
if g.theme == 'duck' and 'style' in request.cookies:
|
2012-06-01 23:36:38 +00:00
|
|
|
resp.delete_cookie('style')
|
2012-09-10 23:11:13 +00:00
|
|
|
elif g.theme != 'duck':
|
2012-06-01 23:36:38 +00:00
|
|
|
resp.set_cookie('style', g.theme)
|
|
|
|
return resp
|
|
|
|
|
2012-06-01 23:15:41 +00:00
|
|
|
|
2012-09-10 12:14:29 +00:00
|
|
|
#######################
|
|
|
|
# Hooks - after request
|
|
|
|
|
|
|
|
@app.after_request
|
|
|
|
def call_after_request_callbacks(response):
|
|
|
|
for callback in getattr(g, 'after_request_callbacks', ()):
|
|
|
|
response = callback(response)
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
2012-09-15 04:54:16 +00:00
|
|
|
##################
|
|
|
|
# Template filters
|
|
|
|
|
|
|
|
@app.template_filter('restructuredtext')
|
|
|
|
def restructuredtext(value):
|
|
|
|
parts = publish_parts(source=value, writer_name="html")
|
|
|
|
return parts['html_body']
|
|
|
|
|
2012-12-03 10:45:35 +00:00
|
|
|
|
2012-09-15 04:54:16 +00:00
|
|
|
################
|
2012-09-10 11:56:51 +00:00
|
|
|
# Error handlers
|
|
|
|
|
2012-06-03 01:06:09 +00:00
|
|
|
@app.errorhandler(404)
|
|
|
|
def page_not_found(error):
|
|
|
|
return render_template('global/error_404.html'), 404
|
2012-09-10 11:28:34 +00:00
|
|
|
|
2012-09-11 00:17:00 +00:00
|
|
|
@app.errorhandler(500)
|
|
|
|
def server_error(error):
|
|
|
|
return render_template('global/error_500.html'), 500
|
|
|
|
|
2012-12-19 13:02:16 +00:00
|
|
|
|
|
|
|
# Import these to ensure they get loaded
|
|
|
|
import templatevars
|
2012-12-19 21:30:06 +00:00
|
|
|
import urls
|