diff --git a/partner_communication/__manifest__.py b/partner_communication/__manifest__.py index b0d020061..44b156191 100644 --- a/partner_communication/__manifest__.py +++ b/partner_communication/__manifest__.py @@ -30,7 +30,7 @@ # pylint: disable=C8101 { "name": "Partner Communication", - "version": "18.0.1.0.1", + "version": "18.0.1.0.2", "category": "Other", "author": "Compassion Switzerland", "license": "AGPL-3", diff --git a/partner_communication/migrations/18.0.1.0.2/post-migration.py b/partner_communication/migrations/18.0.1.0.2/post-migration.py new file mode 100644 index 000000000..5d113a955 --- /dev/null +++ b/partner_communication/migrations/18.0.1.0.2/post-migration.py @@ -0,0 +1,59 @@ +import json +import logging + +from openupgradelib import openupgrade + +_logger = logging.getLogger(__name__) + +# T3274: found while investigating why sponsorship onboarding communications +# crashed - the "Donation - Thank You Letter" template had its ">"/"<"/'"'/"'" +# QWeb comparison/string-literal operators double-escaped +# (e.g. "&gt;" instead of ">"), so Odoo 18's stricter QWeb compiler +# tried to evaluate the still-escaped "&gt;" text as a Python operator +# and crashed. This is a purely mechanical unescape, safe to apply to any +# mail_template regardless of which module (if any) owns it - many of the +# affected templates were created directly via the UI and have no owning +# module at all, so a per-module migration could never reach them. +ENTITY_FIXES = ( + ("&gt;", ">"), + ("&lt;", "<"), + ("&quot;", """), + ("&apos;", "'"), +) + + +def _fix_body(body): + if not body: + return body + for broken, fixed in ENTITY_FIXES: + body = body.replace(broken, fixed) + return body + + +@openupgrade.migrate() +def migrate(env, version): + env.cr.execute( + """ + SELECT id, body_html FROM mail_template + WHERE body_html::text LIKE '%&gt;%' + OR body_html::text LIKE '%&lt;%' + OR body_html::text LIKE '%&quot;%' + OR body_html::text LIKE '%&apos;%' + """ + ) + rows = env.cr.fetchall() + fixed_count = 0 + for template_id, body_html in rows: + fixed = {lang: _fix_body(body) for lang, body in body_html.items()} + if fixed != body_html: + env.cr.execute( + "UPDATE mail_template SET body_html = %s WHERE id = %s", + (json.dumps(fixed), template_id), + ) + fixed_count += 1 + _logger.info( + "T3274: unescaped double-escaped >/</"/' entities " + "in %s/%s mail_template rows", + fixed_count, + len(rows), + )