mirror of
https://github.com/webrecorder/pywb.git
synced 2025-03-28 00:25:21 +01:00
canonical, no-modifier archival url (instead of mp_). When using frames, the page redirects to a 'tf_' page, which then uses replaceHistory() to change url back to canonical form. memento: support for framed replay, include memento headers in top frame bump version to 0.6.2
190 lines
6.2 KiB
Python
190 lines
6.2 KiB
Python
from pywb.utils.timeutils import timestamp_to_datetime
|
|
from pywb.framework.wbrequestresponse import WbResponse
|
|
from pywb.framework.memento import make_timemap, LINK_FORMAT
|
|
|
|
import urlparse
|
|
import logging
|
|
|
|
from os import path
|
|
from itertools import imap
|
|
from jinja2 import Environment
|
|
from jinja2 import FileSystemLoader, PackageLoader, ChoiceLoader
|
|
|
|
|
|
FILTERS = {}
|
|
|
|
|
|
#=================================================================
|
|
class template_filter(object):
|
|
"""
|
|
Decorator for registering a function as a jinja2 filter
|
|
If optional argument is supplied, it is used as the filter name
|
|
Otherwise, the func name is the filter name
|
|
"""
|
|
def __init__(self, param=None):
|
|
if hasattr(param, '__call__'):
|
|
self.name = None
|
|
self.__call__(param)
|
|
else:
|
|
self.name = param
|
|
|
|
def __call__(self, func):
|
|
name = self.name
|
|
if not name:
|
|
name = func.__name__
|
|
|
|
FILTERS[name] = func
|
|
return func
|
|
|
|
|
|
#=================================================================
|
|
# Filters
|
|
@template_filter
|
|
def format_ts(value, format_='%a, %b %d %Y %H:%M:%S'):
|
|
value = timestamp_to_datetime(value)
|
|
return value.strftime(format_)
|
|
|
|
|
|
@template_filter('urlsplit')
|
|
def get_urlsplit(url):
|
|
split = urlparse.urlsplit(url)
|
|
return split
|
|
|
|
|
|
@template_filter()
|
|
def request_hostname(env):
|
|
return env.get('HTTP_HOST', 'localhost')
|
|
|
|
|
|
@template_filter()
|
|
def is_wb_handler(obj):
|
|
if not hasattr(obj, 'handler'):
|
|
return False
|
|
|
|
#return isinstance(obj.handler, WBHandler)
|
|
return obj.handler.__class__.__name__ == "WBHandler"
|
|
|
|
|
|
#=================================================================
|
|
class J2TemplateView(object):
|
|
env_globals = {'static_path': 'static/default',
|
|
'package': 'pywb'}
|
|
|
|
def __init__(self, filename):
|
|
template_dir, template_file = path.split(filename)
|
|
self.template_file = template_file
|
|
|
|
self.jinja_env = self.make_jinja_env(template_dir)
|
|
|
|
def make_jinja_env(self, template_dir):
|
|
loaders = self._make_loaders(template_dir)
|
|
loader = ChoiceLoader(loaders)
|
|
|
|
jinja_env = Environment(loader=loader, trim_blocks=True)
|
|
jinja_env.filters.update(FILTERS)
|
|
jinja_env.globals.update(self.env_globals)
|
|
return jinja_env
|
|
|
|
def _make_loaders(self, template_dir):
|
|
loaders = []
|
|
loaders.append(FileSystemLoader(template_dir))
|
|
# add relative and absolute path loaders for banner support
|
|
loaders.append(FileSystemLoader('.'))
|
|
loaders.append(FileSystemLoader('/'))
|
|
loaders.append(PackageLoader(self.env_globals['package'], template_dir))
|
|
return loaders
|
|
|
|
def render_to_string(self, **kwargs):
|
|
template = self.jinja_env.get_template(self.template_file)
|
|
|
|
template_result = template.render(**kwargs)
|
|
|
|
return template_result
|
|
|
|
def render_response(self, **kwargs):
|
|
template_result = self.render_to_string(**kwargs)
|
|
status = kwargs.get('status', '200 OK')
|
|
content_type = kwargs.get('content_type', 'text/html; charset=utf-8')
|
|
return WbResponse.text_response(template_result.encode('utf-8'),
|
|
status=status,
|
|
content_type=content_type)
|
|
|
|
@staticmethod
|
|
def create_template(filename, desc='', view_class=None):
|
|
if not filename:
|
|
return None
|
|
|
|
if not view_class:
|
|
view_class = J2TemplateView
|
|
|
|
logging.debug('Adding {0}: {1}'.format(desc, filename))
|
|
return view_class(filename)
|
|
|
|
|
|
#=================================================================
|
|
def add_env_globals(glb):
|
|
J2TemplateView.env_globals.update(glb)
|
|
|
|
|
|
#=================================================================
|
|
class HeadInsertView(J2TemplateView):
|
|
def create_insert_func(self, wbrequest,
|
|
include_ts=True):
|
|
|
|
top_url = wbrequest.wb_prefix
|
|
top_url += wbrequest.wb_url.to_str(mod=wbrequest.final_mod)
|
|
|
|
include_wombat = not wbrequest.wb_url.is_banner_only
|
|
|
|
def make_head_insert(rule, cdx):
|
|
return (self.render_to_string(wbrequest=wbrequest,
|
|
cdx=cdx,
|
|
top_url=top_url,
|
|
include_ts=include_ts,
|
|
include_wombat=include_wombat,
|
|
banner_html=self.banner_html,
|
|
rule=rule))
|
|
return make_head_insert
|
|
|
|
@staticmethod
|
|
def init_from_config(config):
|
|
view = config.get('head_insert_view')
|
|
if not view:
|
|
html = config.get('head_insert_html', 'ui/head_insert.html')
|
|
|
|
if html:
|
|
banner_html = config.get('banner_html', 'banner.html')
|
|
view = HeadInsertView(html)
|
|
logging.debug('Adding HeadInsert: {0}, Banner {1}'.
|
|
format(html, banner_html))
|
|
|
|
view.banner_html = banner_html
|
|
|
|
return view
|
|
|
|
|
|
#=================================================================
|
|
# query views
|
|
#=================================================================
|
|
class J2HtmlCapturesView(J2TemplateView):
|
|
def render_response(self, wbrequest, cdx_lines, **kwargs):
|
|
return J2TemplateView.render_response(self,
|
|
cdx_lines=list(cdx_lines),
|
|
url=wbrequest.wb_url.url,
|
|
type=wbrequest.wb_url.type,
|
|
prefix=wbrequest.wb_prefix,
|
|
**kwargs)
|
|
|
|
@staticmethod
|
|
def create_template(filename, desc=''):
|
|
return J2TemplateView.create_template(filename, desc,
|
|
J2HtmlCapturesView)
|
|
|
|
|
|
#=================================================================
|
|
class MementoTimemapView(object):
|
|
def render_response(self, wbrequest, cdx_lines):
|
|
memento_lines = make_timemap(wbrequest, cdx_lines)
|
|
return WbResponse.text_stream(memento_lines,
|
|
content_type=LINK_FORMAT)
|