=== modified file 'Mailman/Utils.py' --- Mailman/Utils.py 2018-07-02 22:37:24 +0000 +++ Mailman/Utils.py 2018-07-03 22:54:00 +0000 @@ -473,7 +473,7 @@ _ampre = re.compile('&((?:#[0-9]+|[a-z]+);)', re.IGNORECASE) -def websafe(s): +def websafe(s, doubleescape=False): # If a user submits a form or URL with post data or query fragments # with multiple occurrences of the same variable, we can get a list # here. Be as careful as possible. @@ -488,8 +488,11 @@ if isinstance(s, str): for k in mm_cfg.BROKEN_BROWSER_REPLACEMENTS: s = s.replace(k, mm_cfg.BROKEN_BROWSER_REPLACEMENTS[k]) - # Don't double escape html entities - return _ampre.sub(r'&\1', cgi.escape(s, quote=True)) + if doubleescape: + return cgi.escape(s, quote=True) + else: + # Don't double escape html entities + return _ampre.sub(r'&\1', cgi.escape(s, quote=True)) def nntpsplit(s): === modified file 'Mailman/htmlformat.py' --- Mailman/htmlformat.py 2018-06-17 23:47:34 +0000 +++ Mailman/htmlformat.py 2018-07-04 00:11:55 +0000 @@ -495,7 +495,9 @@ def __init__(self, name, text='', rows=None, cols=None, wrap='soft', readonly=0): if isinstance(text, str): - safetext = Utils.websafe(text) + # Double escape HTML entities only in readonly areas. + doubleescape = not readonly + safetext = Utils.websafe(text, doubleescape) else: safetext = text self.name = name