# w.c.s. - web application for online forms # Copyright (C) 2005-2010 Entr'ouvert # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . import io import os import re import django.template from django.template import TemplateSyntaxError as DjangoTemplateSyntaxError from django.template import VariableDoesNotExist as DjangoVariableDoesNotExist from django.template import engines from django.template.loader import render_to_string from django.utils.encoding import force_text, smart_text from quixote import get_publisher, get_request, get_response, get_session from quixote.html import TemplateIO, htmlescape, htmltext from . import ezt, force_str def get_theme_directory(theme_id): system_location = os.path.join(get_publisher().data_dir, 'themes', theme_id) local_location = os.path.join(get_publisher().app_dir, 'themes', theme_id) if os.path.exists(local_location): location = local_location elif os.path.exists(system_location): location = system_location else: return None while os.path.islink(location): location = os.path.join(os.path.dirname(location), os.readlink(location)) if not os.path.exists(location): return None return location def html_top(title=None, default_org=None): if not hasattr(get_response(), 'filter'): get_response().filter = {} get_response().filter['title'] = title get_response().filter['default_org'] = default_org def error_page(error_message, error_title=None, location_hint=None): from . import _ if not error_title: error_title = _('Error') kwargs = {'title': error_title} if get_request().is_in_backoffice() and get_request().user and get_request().user.can_go_in_backoffice(): from wcs.qommon.backoffice.menu import html_top as backoffice_html_top get_response().add_javascript(['jquery.js', 'qommon.js', 'gadjo.js']) backoffice_html_top(section='', **kwargs) context = get_decorate_vars('', get_response()) context['error_message'] = error_message return QommonTemplateResponse( templates=['wcs/backoffice/error.html'], context=context, is_django_native=True ) r = TemplateIO(html=True) html_top(**kwargs) r += htmltext('
') r += htmltext('

%s

') % error_message continue_link = htmltext('%s') % (get_publisher().get_root_url(), _('the homepage')) r += htmltext('

%s

') % htmltext(_('Continue to %s')) % continue_link r += htmltext('
') return htmltext(r.getvalue()) def get_decorate_vars(body, response, generate_breadcrumb=True, **kwargs): from .publisher import get_cfg if response.content_type != 'text/html': return {'body': body} body = str(body) if get_request().get_header('x-popup') == 'true': return {'body': body} kwargs = {} for k, v in response.filter.items(): if v: kwargs[k] = str(v) if 'lang' not in kwargs and hasattr(get_request(), 'language'): response.filter['lang'] = get_request().language if ('rel="popup"' in body or 'rel="popup"' in kwargs.get('sidebar', '')) or ( 'data-popup' in body or 'data-popup' in kwargs.get('sidebar', '') ): response.add_javascript(['popup.js', 'widget_list.js']) onload = kwargs.get('onload') org_name = get_cfg('sp', {}).get('organization_name', kwargs.get('default_org', get_publisher().APP_NAME)) site_name = get_cfg('misc', {}).get('sitename', org_name) current_theme = get_cfg('branding', {}).get('theme', get_publisher().default_theme) if kwargs.get('title'): title = kwargs.get('title') page_title = '%s - %s' % (site_name, title) title_or_orgname = title else: page_title = site_name title = None title_or_orgname = site_name script = kwargs.get('script') or '' script += response.get_css_includes_for_header() script += response.get_javascript_for_header() try: user = get_request().user except Exception: user = None if type(user) in (int, str) and get_session(): try: user = get_session().get_user_object() except KeyError: pass root_url = get_publisher().get_application_static_files_root_url() theme_url = '%sthemes/%s' % (root_url, current_theme) is_in_backoffice = response.filter.get('admin_ezt') if is_in_backoffice: header_menu = kwargs.get('header_menu') user_info = kwargs.get('user_info') page_title = kwargs.get('sitetitle', '') + kwargs.get('title', '') subtitle = kwargs.get('subtitle') sidebar = kwargs.get('sidebar') css = root_url + get_publisher().qommon_static_dir + get_publisher().qommon_admin_css extra_head = get_publisher().get_site_option('backoffice_extra_head') app_label = get_publisher().get_site_option('app_label') or 'w.c.s.' else: css = root_url + 'themes/%s/%s.css' % (current_theme, get_publisher().APP_NAME) # this variable is kept in locals() as it was once part of the default # template and existing installations may have template changes that # still have it. prelude = '' if generate_breadcrumb: breadcrumb = '' if hasattr(response, 'breadcrumb') and response.breadcrumb: s = [] path = root_url if is_in_backoffice: path += response.breadcrumb[0][0] response.breadcrumb = response.breadcrumb[1:] total_len = sum(len(str(x[1])) for x in response.breadcrumb if x[1] is not None) for component, label in response.breadcrumb: if component.startswith('http:') or component.startswith('https:'): s.append('%s' % (component, label)) continue if label is not None: if isinstance(label, str): label = htmlescape(label) if not is_in_backoffice and ( total_len > 80 and len(label) > 10 and response.breadcrumb[-1] != (component, label) ): s.append('%s' % (path, component, label, '...')) else: s.append('%s' % (path, component, label)) path += component.split('#')[0] # remove anchor for next parts breadcrumb = ' > '.join(s) vars = response.filter.copy() vars.update(get_publisher().substitutions.get_context_variables()) vars.update(locals()) return vars def render(template_name, context): request = getattr(get_request(), 'django_request', None) result = render_to_string(template_name, context, request=request) return htmltext(force_str(result)) class QommonTemplateResponse: is_django_native = False def __init__(self, templates, context, is_django_native=False): self.templates = templates self.context = context self.is_django_native = is_django_native def add_media(self): # run add_media so we get them in the page if 'html_form' in self.context: self.context['html_form'].add_media() if 'form' in self.context and hasattr(self.context['form'], 'add_media'): # legacy name, conflicting with formdata "form*" variables self.context['form'].add_media() class TemplateError(Exception): def __init__(self, msg, params=()): self.msg = msg self.params = params def __str__(self): from . import misc return misc.site_encode(smart_text(self.msg) % self.params) def ezt_raises(exception, on_parse=False): from . import _ parts = [] parts.append( { ezt.ArgCountSyntaxError: _('wrong number of arguments'), ezt.UnknownReference: _('unknown reference'), ezt.NeedSequenceError: _('sequence required'), ezt.UnclosedBlocksError: _('unclosed block'), ezt.UnmatchedEndError: _('unmatched [end]'), ezt.UnmatchedElseError: _('unmatched [else]'), ezt.BaseUnavailableError: _('unavailable base location'), ezt.BadFormatConstantError: _('bad format constant'), ezt.UnknownFormatConstantError: _('unknown format constant'), }.get(exception.__class__, _('unknown error')) ) if exception.line is not None: parts.append( _('at line %(line)d and column %(column)d') % {'line': exception.line + 1, 'column': exception.column + 1} ) if on_parse: message = _('syntax error in ezt template: %s') else: message = _('failure to render ezt template: %s') raise TemplateError(message % ' '.join([str(x) for x in parts])) class Template: def __init__(self, value, raises=False, ezt_format=ezt.FORMAT_RAW, ezt_only=False, autoescape=True): '''Guess kind of template (Django or ezt), and parse it''' self.value = value self.raises = raises if ('{{' in value or '{%' in value) and not ezt_only: # Django template self.format = 'django' self.render = self.django_render if autoescape is False: value = '{%% autoescape off %%}%s{%% endautoescape %%}' % value try: self.template = engines['django'].from_string(value) except DjangoTemplateSyntaxError as e: if raises: from . import _ raise TemplateError(_('syntax error in Django template: %s'), e) self.render = self.null_render elif '[' in value and '