diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py index 992808c631..2012899416 100644 --- a/src/pretix/base/pdf.py +++ b/src/pretix/base/pdf.py @@ -2,7 +2,6 @@ import copy import itertools import logging import os -import re import subprocess import tempfile import uuid @@ -10,14 +9,13 @@ from collections import OrderedDict from functools import partial from io import BytesIO -import bleach from arabic_reshaper import ArabicReshaper from bidi.algorithm import get_display from django.conf import settings from django.contrib.staticfiles import finders from django.dispatch import receiver from django.utils.formats import date_format -from django.utils.html import escape +from django.utils.html import conditional_escape from django.utils.timezone import now from django.utils.translation import ugettext_lazy as _ from PyPDF2 import PdfFileReader @@ -65,32 +63,32 @@ DEFAULT_VARIABLES = OrderedDict(( ("item", { "label": _("Product name"), "editor_sample": _("Sample product"), - "evaluate": lambda orderposition, order, event: escape(str(orderposition.item.name)) + "evaluate": lambda orderposition, order, event: str(orderposition.item.name) }), ("variation", { "label": _("Variation name"), "editor_sample": _("Sample variation"), - "evaluate": lambda op, order, event: escape(str(op.variation) if op.variation else '') + "evaluate": lambda op, order, event: str(op.variation) if op.variation else '' }), ("item_description", { "label": _("Product description"), "editor_sample": _("Sample product description"), - "evaluate": lambda orderposition, order, event: escape(str(orderposition.item.description)) + "evaluate": lambda orderposition, order, event: str(orderposition.item.description) }), ("itemvar", { "label": _("Product name and variation"), "editor_sample": _("Sample product – sample variation"), - "evaluate": lambda orderposition, order, event: escape(( + "evaluate": lambda orderposition, order, event: ( '{} - {}'.format(orderposition.item.name, orderposition.variation) if orderposition.variation else str(orderposition.item.name) - )) + ) }), ("item_category", { "label": _("Product category"), "editor_sample": _("Ticket category"), - "evaluate": lambda orderposition, order, event: escape(( + "evaluate": lambda orderposition, order, event: ( str(orderposition.item.category.name) if orderposition.item.category else "" - )) + ) }), ("price", { "label": _("Price"), @@ -109,12 +107,12 @@ DEFAULT_VARIABLES = OrderedDict(( ("attendee_name", { "label": _("Attendee name"), "editor_sample": _("John Doe"), - "evaluate": lambda op, order, ev: escape(op.attendee_name or (op.addon_to.attendee_name if op.addon_to else '')) + "evaluate": lambda op, order, ev: op.attendee_name or (op.addon_to.attendee_name if op.addon_to else '') }), ("event_name", { "label": _("Event name"), "editor_sample": _("Sample event name"), - "evaluate": lambda op, order, ev: escape(str(ev.name)) + "evaluate": lambda op, order, ev: str(ev.name) }), ("event_date", { "label": _("Event date"), @@ -190,27 +188,27 @@ DEFAULT_VARIABLES = OrderedDict(( ("event_location", { "label": _("Event location"), "editor_sample": _("Random City"), - "evaluate": lambda op, order, ev: str(ev.location).replace("\n", "
\n") + "evaluate": lambda op, order, ev: str(ev.location) }), ("invoice_name", { "label": _("Invoice address name"), "editor_sample": _("John Doe"), - "evaluate": lambda op, order, ev: escape(order.invoice_address.name if getattr(order, 'invoice_address', None) else '') + "evaluate": lambda op, order, ev: order.invoice_address.name if getattr(order, 'invoice_address', None) else '' }), ("invoice_company", { "label": _("Invoice address company"), "editor_sample": _("Sample company"), - "evaluate": lambda op, order, ev: escape(order.invoice_address.company if getattr(order, 'invoice_address', None) else '') + "evaluate": lambda op, order, ev: order.invoice_address.company if getattr(order, 'invoice_address', None) else '' }), ("invoice_city", { "label": _("Invoice address city"), "editor_sample": _("Sample city"), - "evaluate": lambda op, order, ev: escape(order.invoice_address.city if getattr(order, 'invoice_address', None) else '') + "evaluate": lambda op, order, ev: order.invoice_address.city if getattr(order, 'invoice_address', None) else '' }), ("addons", { "label": _("List of Add-Ons"), "editor_sample": _("Addon 1\nAddon 2"), - "evaluate": lambda op, order, ev: "
".join([ + "evaluate": lambda op, order, ev: "\n".join([ '{} - {}'.format(p.item, p.variation) if p.variation else str(p.item) for p in ( op.addons.all() if 'addons' in getattr(op, '_prefetched_objects_cache', {}) @@ -222,7 +220,7 @@ DEFAULT_VARIABLES = OrderedDict(( ("organizer", { "label": _("Organizer name"), "editor_sample": _("Event organizer company"), - "evaluate": lambda op, order, ev: escape(str(order.event.organizer.name)) + "evaluate": lambda op, order, ev: str(order.event.organizer.name) }), ("organizer_info_text", { "label": _("Organizer info text"), @@ -302,7 +300,7 @@ def variables_from_questions(sender, *args, **kwargs): if not a: return "" else: - return escape(str(a)).replace("\n", "
\n") + return str(a) d = {} for q in sender.questions.all(): @@ -316,12 +314,12 @@ def variables_from_questions(sender, *args, **kwargs): def _get_attendee_name_part(key, op, order, ev): if isinstance(key, tuple): - return ' '.join(_get_attendee_name_part(c[0], op, order, ev) for c in key) - return escape(op.attendee_name_parts.get(key, '')) + return ' '.join(p for p in [_get_attendee_name_part(c[0], op, order, ev) for c in key] if p) + return op.attendee_name_parts.get(key, '') def _get_ia_name_part(key, op, order, ev): - return escape(order.invoice_address.name_parts.get(key, '') if getattr(order, 'invoice_address', None) else '') + return order.invoice_address.name_parts.get(key, '') if getattr(order, 'invoice_address', None) else '' def get_variables(event): @@ -432,7 +430,7 @@ class Renderer: if not o['content']: return '(error)' if o['content'] == 'other': - return o['text'].replace("\n", "
\n") + return o['text'] elif o['content'].startswith('meta:'): return ev.meta_data.get(o['content'][5:]) or '' elif o['content'] in self.variables: @@ -464,13 +462,9 @@ class Renderer: textColor=Color(o['color'][0] / 255, o['color'][1] / 255, o['color'][2] / 255), alignment=align_map[o['align']] ) - text = re.sub( - "]*>", "
", - bleach.clean( - self._get_text_content(op, order, o) or "", - tags=["br"], attributes={}, styles=[], strip=True - ) - ) + text = conditional_escape( + self._get_text_content(op, order, o) or "", + ).replace("\n", "
\n") # reportlab does not support RTL, ligature-heavy scripts like Arabic. Therefore, we use ArabicReshaper # to resolve all ligatures and python-bidi to switch RTL texts.