comparison roundup/cgi/templating.py @ 5800:1a835db41674

Call cgi.escape only on python 2. Replace with html.escapeif it can be found.
author John Rouillard <rouilj@ieee.org>
date Tue, 11 Jun 2019 21:29:24 -0400
parents 97e2125e064c
children 936275dfe1fa
comparison
equal deleted inserted replaced
5799:7ba0ee980fc7 5800:1a835db41674
22 22
23 import base64, cgi, re, os.path, mimetypes, csv, string 23 import base64, cgi, re, os.path, mimetypes, csv, string
24 import calendar 24 import calendar
25 import textwrap 25 import textwrap
26 import time, hashlib 26 import time, hashlib
27
28 try:
29 from html import escape as html_escape # python 3
30 except ImportError:
31 from cgi import escape as html_escape # python 2 fallback
27 32
28 from roundup.anypy import urllib_ 33 from roundup.anypy import urllib_
29 from roundup import hyperdb, date, support 34 from roundup import hyperdb, date, support
30 from roundup import i18n 35 from roundup import i18n
31 from roundup.i18n import _ 36 from roundup.i18n import _
428 dic['id'] = dic['name'] 433 dic['id'] = dic['name']
429 except KeyError: 434 except KeyError:
430 pass 435 pass
431 436
432 def cgi_escape_attrs(**attrs): 437 def cgi_escape_attrs(**attrs):
433 return ' '.join(['%s="%s"'%(k,cgi.escape(str(v), True)) 438 return ' '.join(['%s="%s"'%(k,html_escape(str(v), True))
434 for k,v in sorted(attrs.items())]) 439 for k,v in sorted(attrs.items())])
435 440
436 def input_html4(**attrs): 441 def input_html4(**attrs):
437 """Generate an 'input' (html4) element with given attributes""" 442 """Generate an 'input' (html4) element with given attributes"""
438 _set_input_default_args(attrs) 443 _set_input_default_args(attrs)
1042 # there's no labelprop! 1047 # there's no labelprop!
1043 try: 1048 try:
1044 if labelprop is not None and \ 1049 if labelprop is not None and \
1045 labelprop != 'id': 1050 labelprop != 'id':
1046 label = linkcl.get(linkid, labelprop) 1051 label = linkcl.get(linkid, labelprop)
1047 label = cgi.escape(label) 1052 label = html_escape(label)
1048 except IndexError: 1053 except IndexError:
1049 comments['no_link'] = self._( 1054 comments['no_link'] = self._(
1050 "<strike>The linked node" 1055 "<strike>The linked node"
1051 " no longer exists</strike>") 1056 " no longer exists</strike>")
1052 subml.append('<strike>%s</strike>'%label) 1057 subml.append('<strike>%s</strike>'%label)
1067 # if we have a label property, try to use it 1072 # if we have a label property, try to use it
1068 # TODO: test for node existence even when 1073 # TODO: test for node existence even when
1069 # there's no labelprop! 1074 # there's no labelprop!
1070 if labelprop is not None and labelprop != 'id': 1075 if labelprop is not None and labelprop != 'id':
1071 try: 1076 try:
1072 label = cgi.escape(linkcl.get(args[k], 1077 label = html_escape(linkcl.get(args[k],
1073 labelprop)) 1078 labelprop))
1074 except IndexError: 1079 except IndexError:
1075 comments['no_link'] = self._( 1080 comments['no_link'] = self._(
1076 "<strike>The linked node" 1081 "<strike>The linked node"
1077 " no longer exists</strike>") 1082 " no longer exists</strike>")
1107 if k in current and current[k] is not None: 1112 if k in current and current[k] is not None:
1108 cell[-1] += ' -> %s'%current[k] 1113 cell[-1] += ' -> %s'%current[k]
1109 current[k] = val 1114 current[k] = val
1110 1115
1111 elif isinstance(prop, hyperdb.String) and args[k]: 1116 elif isinstance(prop, hyperdb.String) and args[k]:
1112 val = cgi.escape(args[k]) 1117 val = html_escape(args[k])
1113 cell.append('%s: %s'%(self._(k), val)) 1118 cell.append('%s: %s'%(self._(k), val))
1114 if k in current and current[k] is not None: 1119 if k in current and current[k] is not None:
1115 cell[-1] += ' -> %s'%current[k] 1120 cell[-1] += ' -> %s'%current[k]
1116 current[k] = val 1121 current[k] = val
1117 1122
1153 # if the user's an itemid, figure the username (older journals 1158 # if the user's an itemid, figure the username (older journals
1154 # have the username) 1159 # have the username)
1155 if dre.match(user): 1160 if dre.match(user):
1156 user = self._db.user.get(user, 'username') 1161 user = self._db.user.get(user, 'username')
1157 l.append('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>'%( 1162 l.append('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>'%(
1158 date_s, cgi.escape(user), self._(action), arg_s)) 1163 date_s, html_escape(user), self._(action), arg_s))
1159 if comments: 1164 if comments:
1160 l.append(self._( 1165 l.append(self._(
1161 '<tr><td colspan=4><strong>Note:</strong></td></tr>')) 1166 '<tr><td colspan=4><strong>Note:</strong></td></tr>'))
1162 for entry in comments.values(): 1167 for entry in comments.values():
1163 l.append('<tr><td colspan=4>%s</td></tr>'%entry) 1168 l.append('<tr><td colspan=4>%s</td></tr>'%entry)
1488 return self._('[hidden]') 1493 return self._('[hidden]')
1489 1494
1490 if self._value is None: 1495 if self._value is None:
1491 return '' 1496 return ''
1492 if escape: 1497 if escape:
1493 s = cgi.escape(str(self._value)) 1498 s = html_escape(str(self._value))
1494 else: 1499 else:
1495 s = str(self._value) 1500 s = str(self._value)
1496 if hyperlink: 1501 if hyperlink:
1497 # no, we *must* escape this text 1502 # no, we *must* escape this text
1498 if not escape: 1503 if not escape:
1499 s = cgi.escape(s) 1504 s = html_escape(s)
1500 s = self.hyper_re.sub(self._hyper_repl, s) 1505 s = self.hyper_re.sub(self._hyper_repl, s)
1501 return s 1506 return s
1502 1507
1503 def wrapped(self, escape=1, hyperlink=1): 1508 def wrapped(self, escape=1, hyperlink=1):
1504 """Render a "wrapped" representation of the property. 1509 """Render a "wrapped" representation of the property.
1518 1523
1519 if self._value is None: 1524 if self._value is None:
1520 return '' 1525 return ''
1521 s = '\n'.join(textwrap.wrap(str(self._value), 80)) 1526 s = '\n'.join(textwrap.wrap(str(self._value), 80))
1522 if escape: 1527 if escape:
1523 s = cgi.escape(s) 1528 s = html_escape(s)
1524 if hyperlink: 1529 if hyperlink:
1525 # no, we *must* escape this text 1530 # no, we *must* escape this text
1526 if not escape: 1531 if not escape:
1527 s = cgi.escape(s) 1532 s = html_escape(s)
1528 s = self.hyper_re.sub(self._hyper_repl, s) 1533 s = self.hyper_re.sub(self._hyper_repl, s)
1529 return s 1534 return s
1530 1535
1531 def stext(self, escape=0, hyperlink=1): 1536 def stext(self, escape=0, hyperlink=1):
1532 """ Render the value of the property as StructuredText. 1537 """ Render the value of the property as StructuredText.
1582 return '<pre>%s</pre>'%self.plain() 1587 return '<pre>%s</pre>'%self.plain()
1583 1588
1584 if self._value is None: 1589 if self._value is None:
1585 value = '' 1590 value = ''
1586 else: 1591 else:
1587 value = cgi.escape(str(self._value)) 1592 value = html_escape(str(self._value))
1588 1593
1589 value = '&quot;'.join(value.split('"')) 1594 value = '&quot;'.join(value.split('"'))
1590 name = self._formname 1595 name = self._formname
1591 passthrough_args = cgi_escape_attrs(**kwargs) 1596 passthrough_args = cgi_escape_attrs(**kwargs)
1592 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"' 1597 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"'
1610 name = name.replace('.', ' ') 1615 name = name.replace('.', ' ')
1611 value = '%s at %s ...'%(name, domain) 1616 value = '%s at %s ...'%(name, domain)
1612 else: 1617 else:
1613 value = value.replace('.', ' ') 1618 value = value.replace('.', ' ')
1614 if escape: 1619 if escape:
1615 value = cgi.escape(value) 1620 value = html_escape(value)
1616 return value 1621 return value
1617 1622
1618 class PasswordHTMLProperty(HTMLProperty): 1623 class PasswordHTMLProperty(HTMLProperty):
1619 def plain(self, escape=0): 1624 def plain(self, escape=0):
1620 """ Render a "plain" representation of the property 1625 """ Render a "plain" representation of the property
1627 try: 1632 try:
1628 value = self._value.dummystr() 1633 value = self._value.dummystr()
1629 except AttributeError: 1634 except AttributeError:
1630 value = self._('[hidden]') 1635 value = self._('[hidden]')
1631 if escape: 1636 if escape:
1632 value = cgi.escape(value) 1637 value = html_escape(value)
1633 return value 1638 return value
1634 1639
1635 def field(self, size=30, **kwargs): 1640 def field(self, size=30, **kwargs):
1636 """ Render a form edit field for the property. 1641 """ Render a form edit field for the property.
1637 1642
2089 except IndexError: 2094 except IndexError:
2090 value = self._value 2095 value = self._value
2091 else : 2096 else :
2092 value = self._value 2097 value = self._value
2093 if escape: 2098 if escape:
2094 value = cgi.escape(value) 2099 value = html_escape(value)
2095 return value 2100 return value
2096 2101
2097 def field(self, showid=0, size=None, **kwargs): 2102 def field(self, showid=0, size=None, **kwargs):
2098 """ Render a form edit field for the property 2103 """ Render a form edit field for the property
2099 2104
2241 2246
2242 # and generate 2247 # and generate
2243 tr = str 2248 tr = str
2244 if translate: 2249 if translate:
2245 tr = self._ 2250 tr = self._
2246 lab = cgi.escape(tr(lab)) 2251 lab = html_escape(tr(lab))
2247 l.append('<option %svalue="%s">%s</option>'%(s, optionid, lab)) 2252 l.append('<option %svalue="%s">%s</option>'%(s, optionid, lab))
2248 l.append('</select>') 2253 l.append('</select>')
2249 return '\n'.join(l) 2254 return '\n'.join(l)
2250 # def checklist(self, ...) 2255 # def checklist(self, ...)
2251 2256
2340 else: 2345 else:
2341 label = v 2346 label = v
2342 labels.append(label) 2347 labels.append(label)
2343 value = ', '.join(labels) 2348 value = ', '.join(labels)
2344 if escape: 2349 if escape:
2345 value = cgi.escape(value) 2350 value = html_escape(value)
2346 return value 2351 return value
2347 2352
2348 def field(self, size=30, showid=0, **kwargs): 2353 def field(self, size=30, showid=0, **kwargs):
2349 """ Render a form edit field for the property 2354 """ Render a form edit field for the property
2350 2355
2477 2482
2478 # and generate 2483 # and generate
2479 tr = str 2484 tr = str
2480 if translate: 2485 if translate:
2481 tr = self._ 2486 tr = self._
2482 lab = cgi.escape(tr(lab)) 2487 lab = html_escape(tr(lab))
2483 l.append('<option %svalue="%s">%s</option>'%(s, optionid, 2488 l.append('<option %svalue="%s">%s</option>'%(s, optionid,
2484 lab)) 2489 lab))
2485 l.append('</select>') 2490 l.append('</select>')
2486 return '\n'.join(l) 2491 return '\n'.join(l)
2487 2492
3080 """URL-quote the supplied text.""" 3085 """URL-quote the supplied text."""
3081 return urllib_.quote(url) 3086 return urllib_.quote(url)
3082 3087
3083 def html_quote(self, html): 3088 def html_quote(self, html):
3084 """HTML-quote the supplied text.""" 3089 """HTML-quote the supplied text."""
3085 return cgi.escape(html) 3090 return html_escape(html)
3086 3091
3087 def __getattr__(self, name): 3092 def __getattr__(self, name):
3088 """Try the tracker's templating_utils.""" 3093 """Try the tracker's templating_utils."""
3089 if not hasattr(self.client.instance, 'templating_utils'): 3094 if not hasattr(self.client.instance, 'templating_utils'):
3090 # backwards-compatibility 3095 # backwards-compatibility

Roundup Issue Tracker: http://roundup-tracker.org/