1
0
mirror of https://github.com/webrecorder/pywb.git synced 2025-03-28 00:25:21 +01:00
pywb/pywb/webapp/views.py
Ilya Kreymer 4a1cc46fa3 framed replay: invert framed replay paradigm, replay always uses
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
2014-10-18 11:21:07 -07:00

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)