Как избежать экранирования символов HTML в веб-фреймворке Bottle Python?

Вопрос

Как я могу предотвратить экранирование символов в Bottle - Python Web Framework?

Фон

Я делаю веб-приложение с текстами песен в Bottle (python), и я проверяю все данные правильно, прежде чем вставлять их в базу данных, поэтому на данный момент у меня есть форма с именем "song name", "artist". "," лирика " (в текстовой области) и все.

Когда форма отправляется, она загружает страницу, содержащую три входных значения, упомянутых выше (песню, исполнителя и текст песни), и все работает, как и ожидалось, но html текста песни экранируется (перед отправкой текста в шаблон я заменил все \n с <br>).

Итак, я провел исследование и из этого урока с bottlepy.org и обнаружил, что Bottle экранирует html-теги, чтобы предотвратить атаки XSS, и вы можете отключить это, поставив "!" перед именем переменной, УДИВИТЕЛЬНЫЙ! Я нашел решение, но... когда я попытался использовать его, он выдал ошибку:

Ошибка - Скриншот ошибки на компьютере

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 - суть на 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 шаблон - суть на github

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

Вот как это работает / выглядит, если я позволю Бутылке уйти от моих текстов HTML (обратите внимание, как <br> отображается в виде простого текста):

И, наконец, вот как это выглядит

1 ответ

Решение

Вы должны поставить восклицательный знак сразу после открытия {{ чтобы бутылка узнала это:

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

Желательно, чтобы вы вообще пропустили пробелы, чтобы быть в безопасности:

<div>Letra: {{!letra['letra']}}</div>
Другие вопросы по тегам