Why does this Jinja nl2br filter slip away, but not <p>?
I am trying to implement this Jinja filter nl2br. It works correctly, except it is being added <br>. This is strange for me, because it is <p>not escaped, and they are all on the same line.
I use a flask, so Jinja is included autoescape. I really hoped when I found this guy , saying that autoescapethey escape(value)could cause double-escaping, but the removal escape()did not help.
Here is my modified code and its output:
@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
_paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
result = u'\n\n'.join(u'<p>%s</p>' % escape(p.replace(u'\r\n', u'<br>\n')) for p in _paragraph_re.split(value))
if eval_ctx.autoescape:
result = Markup(result)
return result
:
u'1\r\n2\r\n\r\n3\r\n4\r\n\r\n5\r\n6\r\n7'
output:
<p>1<br>
2</p>
<p>3<br>
4</p>
<p>5<br>
6<br>
7</p>
desired result:
<p>1<br>2</p>
<p>3<br>4</p>
<p>5<br>6<br>7</p>
What can lead to escaping <br>but resolution <p>?
? ?
@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
_paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\r\n', u'<br/>') for p in _paragraph_re.split(value))
if eval_ctx.autoescape:
result = Markup(result)
return result
, :
{{ '1\r\n2\r\n\r\n3\r\n4\r\n\r\n5\r\n6\r\n7' | nl2br}}
<p>1<br/>2</p>
<p>3<br/>4</p>
<p>5<br/>6<br/>7</p>
nl2br Markup . value - , <br> . , <br> :
@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
_paragraph_re = re.compile(r'(?:\r\n|\r(?!\n)|\n){2,}')
result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', Markup('<br>\n'))
for p in _paragraph_re.split(value))
if eval_ctx.autoescape:
result = Markup(result)
return result
. \n.
, :
Markup, Markup:
>>> Markup("hello there").split()
[Markup(u'hello'), Markup(u'there')]
Jinja :
- , , escape().
nl2br, , :
result = u'\n\n'.join(u'<p>%s</p>' % p.replace(u'\n', u'<br>\n')
for p in _paragraph_re.split(value))
u'\n\n' u'<br>\n' unicode, p Markup value, Markup. p.replace Unicode Markup p, Markup .
<p> - , Python , % unicode, unicode . Markup , . result .
2 , , , <br/>, XSS. :
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";
alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--
></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
The original nl2br jinja snippet from Dan Jacob is almost there:
import re
from jinja2 import evalcontextfilter, Markup, escape
_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
app = Flask(__name__)
@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n') \
for p in _paragraph_re.split(escape(value)))
if eval_ctx.autoescape:
result = Markup(result)
return result
Just combine this with @joemaller's answer about creating an object Markup('<br/>\n'). I.e:
result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', Markup('<br/>\n')) \
for p in _paragraph_re.split(escape(value)))