Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid escaping html characters in bottle python web framework?

Tags:

python

bottle

Question

How can I prevent escaping characters in Bottle - Python Web Framework?

Background

I'm making a songs lyrics webapp in Bottle (python), and I'm testing all the data is correct before inserting it to the database, so, for now, I basically have a form that has "song name", "artist", "lyrics" (in a textarea) and that's it.

When the form submits it loads a page containing the three input values mentioned above (song, artist and lyrics) and everything is working as expected but the lyrics' html is being escaped (before sending the lyrics to the template I replaced all the \n with <br>).

So I did my research and from this tutorial from bottlepy.org and found that Bottle escapes the html tags to prevent XSS attacks and you can disable this by putting a "!" before the variable name, AWESOME! I found the solution, but... when I tried to use it it threw an error:

Error - Screenshot of Error on computer

Exception:

SyntaxError('invalid syntax', ('H:\\Server\\htdocs\\letras\\prueba.tpl', 4, 27, "u'<div>Letra: ', _escape( !letra['letra'] ), u'</div>'])\n"))

Traceback (most recent call last):
    File "H:\Server\htdocs\letras\bottle.py", line 764, in _handle
      return route.call(**args)
    File "H:\Server\htdocs\letras\bottle.py", line 1575, in wrapper
      rv = callback(*a, **ka)
    File "index.py", line 41, in guardar_letra
      return template('prueba.tpl', letra = data)
    File "H:\Server\htdocs\letras\bottle.py", line 3117, in template
      return TEMPLATES[tplid].render(kwargs)
    File "H:\Server\htdocs\letras\bottle.py", line 3090, in render
      self.execute(stdout, kwargs)
    File "H:\Server\htdocs\letras\bottle.py", line 3078, in execute
      eval(self.co, env)
    File "H:\Server\htdocs\letras\bottle.py", line 185, in __get__
      value = obj.__dict__[self.func.__name__] = self.func(obj)
    File "H:\Server\htdocs\letras\bottle.py", line 2977, in co
      return compile(self.code, self.filename or '<string>', 'exec')
    File "H:\Server\htdocs\letras\prueba.tpl", line 4
      u'<div>Letra: ', _escape( !letra['letra'] ), u'</div>'])
                                ^
  SyntaxError: invalid syntax

index.py - gist on github

from bottle import Bottle, route, run, template, static_file, get, post, request, response
from passlib.hash import sha256_crypt
import MySQLdb as mdb
import time
import re

@get('/enviar')
def enviar_letra():
    return template('enviar_letra.tpl')

@post('/enviar')
def guardar_letra():
    titulo = request.forms.get('titulo').capitalize() # Gets the song title from the form
    artista = request.forms.get('artista') # Gets the artist
    letra = request.forms.get('letra') # Gets the lyrics
    fecha_envio = time.strftime('%Y-%m-%d %H:%M:%S') # Date the lyrics were sent
    titulo = re.sub('[^\w|!|\s|\.|,]', '', titulo) # I delete every character except: words, exclamation, spaces, dots, commas
    url = titulo + "-" + artista # concatenate the song's title and the artist name to make a nice url
    url = re.sub('\W+|_', '-', url).lower() # lower all the characters from the url
    url = url.strip("-") # strips "-" at the beginning and the end
    letra = letra.replace("\n", "<br>") # replaces \n from the lyrics text area with <br>
    data = { "titulo": titulo, "artista": artista, "letra": letra, "url": url, "Fecha_envio": fecha_envio } # song dictionary
    return template('prueba.tpl', letra = data) # loads prueba.tpl template and send "data" dictionary as "letra" (letra is lyric in spanish)

run(host='localhost', port=8080, debug=True)

HTML template - gist on github

<h1>Letra de {{ letra['titulo'] }}</h1>
<h2>Por: {{ letra['artista'] }}</h2>
<div>Fecha: {{ letra['Fecha_envio'] }}</div>
<div>Letra: {{ !letra['letra'] }}</div>

Here's how it works/looks if I let Bottle escape my lyrics html (notice how <br> is being displayed as plain text):

http://i.stack.imgur.com/fxz7o.png

And finally, this is how ITS SUPPOSED to look

http://i.stack.imgur.com/6b58J.png

like image 965
kustomrtr Avatar asked Jun 22 '13 08:06

kustomrtr


1 Answers

You need to place the exclamation mark right after the opening {{ for bottle to recognize it:

<div>Letra: {{! letra['letra'] }}</div>

Preferably, you want to omit the spaces there altogether, to be on the safe side:

<div>Letra: {{!letra['letra']}}</div>
like image 55
Martijn Pieters Avatar answered Sep 30 '22 16:09

Martijn Pieters