mirror of
https://github.com/pretix/pretix.git
synced 2026-05-07 15:34:02 +00:00
Invoice: Improve handling of special characters in file names (#3347)
Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
@@ -466,9 +466,17 @@ def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: st
|
|||||||
for inv in invoices:
|
for inv in invoices:
|
||||||
if inv.file:
|
if inv.file:
|
||||||
try:
|
try:
|
||||||
|
# We try to give the invoice a more human-readable name, e.g. "Invoice_ABC-123.pdf" instead of
|
||||||
|
# just "ABC-123.pdf", but we only do so if our currently selected language allows to do this
|
||||||
|
# as ASCII text. For example, we would not want a "فاتورة_" prefix for our filename since this
|
||||||
|
# has shown to cause deliverability problems of the email and deliverability wins.
|
||||||
|
filename = pgettext('invoice', 'Invoice {num}').format(num=inv.number).replace(' ', '_') + '.pdf'
|
||||||
|
if not re.match("^[a-zA-Z0-9-_%./,&:# ]+$", filename):
|
||||||
|
filename = inv.number.replace(' ', '_') + '.pdf'
|
||||||
|
filename = re.sub("[^a-zA-Z0-9-_.]+", "_", filename)
|
||||||
with language(inv.order.locale):
|
with language(inv.order.locale):
|
||||||
email.attach(
|
email.attach(
|
||||||
pgettext('invoice', 'Invoice {num}').format(num=inv.number).replace(' ', '_') + '.pdf',
|
filename,
|
||||||
inv.file.file.read(),
|
inv.file.file.read(),
|
||||||
'application/pdf'
|
'application/pdf'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -633,6 +633,17 @@ DEFAULTS = {
|
|||||||
"used at most once over all of your events. This setting only affects future invoices. You can "
|
"used at most once over all of your events. This setting only affects future invoices. You can "
|
||||||
"use %Y (with century) %y (without century) to insert the year of the invoice, or %m and %d for "
|
"use %Y (with century) %y (without century) to insert the year of the invoice, or %m and %d for "
|
||||||
"the day of month."),
|
"the day of month."),
|
||||||
|
validators=[
|
||||||
|
RegexValidator(
|
||||||
|
# We actually allow more characters than we name in the error message since some of these characters
|
||||||
|
# are in active use at the time of the introduction of this validation, so we can't really forbid
|
||||||
|
# them, but we don't think they belong in an invoice number and don't want to advertise them.
|
||||||
|
regex="^[a-zA-Z0-9-_%./,&:# ]+$",
|
||||||
|
message=lazy(lambda *args: _('Please only use the characters {allowed} in this field.').format(
|
||||||
|
allowed='A-Z, a-z, 0-9, -./:#'
|
||||||
|
), str)()
|
||||||
|
)
|
||||||
|
],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'invoice_numbers_prefix_cancellations': {
|
'invoice_numbers_prefix_cancellations': {
|
||||||
@@ -644,6 +655,17 @@ DEFAULTS = {
|
|||||||
label=_("Invoice number prefix for cancellations"),
|
label=_("Invoice number prefix for cancellations"),
|
||||||
help_text=_("This will be prepended to invoice numbers of cancellations. If you leave this field empty, "
|
help_text=_("This will be prepended to invoice numbers of cancellations. If you leave this field empty, "
|
||||||
"the same numbering scheme will be used that you configured for regular invoices."),
|
"the same numbering scheme will be used that you configured for regular invoices."),
|
||||||
|
validators=[
|
||||||
|
RegexValidator(
|
||||||
|
# We actually allow more characters than we name in the error message since some of these characters
|
||||||
|
# are in active use at the time of the introduction of this validation, so we can't really forbid
|
||||||
|
# them, but we don't think they belong in an invoice number and don't want to advertise them.
|
||||||
|
regex="^[a-zA-Z0-9-_%./,&:# ]+$",
|
||||||
|
message=lazy(lambda *args: _('Please only use the characters {allowed} in this field.').format(
|
||||||
|
allowed='A-Z, a-z, 0-9, -./:#'
|
||||||
|
), str)()
|
||||||
|
)
|
||||||
|
],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'invoice_renderer_highlight_order_code': {
|
'invoice_renderer_highlight_order_code': {
|
||||||
|
|||||||
@@ -1512,7 +1512,7 @@ class InvoiceDownload(EventPermissionRequiredMixin, View):
|
|||||||
invoice_pdf_task.apply(args=(self.invoice.pk,))
|
invoice_pdf_task.apply(args=(self.invoice.pk,))
|
||||||
return self.get(request, *args, **kwargs)
|
return self.get(request, *args, **kwargs)
|
||||||
|
|
||||||
resp['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(self.invoice.number)
|
resp['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(re.sub("[^a-zA-Z0-9-_.]+", "_", self.invoice.number))
|
||||||
resp._csp_ignore = True # Some browser's PDF readers do not work with CSP
|
resp._csp_ignore = True # Some browser's PDF readers do not work with CSP
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|||||||
@@ -1235,7 +1235,7 @@ class InvoiceDownload(EventViewMixin, OrderDetailMixin, View):
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
invoice_pdf_task.apply(args=(invoice.pk,))
|
invoice_pdf_task.apply(args=(invoice.pk,))
|
||||||
return self.get(request, *args, **kwargs)
|
return self.get(request, *args, **kwargs)
|
||||||
resp['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(invoice.number)
|
resp['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(re.sub("[^a-zA-Z0-9-_.]+", "_", invoice.number))
|
||||||
resp._csp_ignore = True # Some browser's PDF readers do not work with CSP
|
resp._csp_ignore = True # Some browser's PDF readers do not work with CSP
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user