Hi,

the behaviour of django for fields that contain html markup ("<" ...)  
is wrong, at least in version 0.91.

First, the admin pages do not html escape these. There might be  
corner cases when this is intended, but it seems very dangerous.

Second, regarding Template, I think the default not to html escape  
variable nodes is not the right one. I think the normal case should  
be to escape these, unless otherwise noted.

I've written a derived HTMLTemplate class for myself that uses a  
different VariableNode to achieve this effect, and attached this if  
you're interested.

Now, did I miss something and is this already fixed? Should this be  
treated differently? How do other people handle this?

If you're positive about my way I'll polish my stuff up for inclusion  
with the contribs.


Michael

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers
-~----------~----~----~----~------~----~------~--~---
"""
A Template subclass that html-escapes all strings passed from the context,
except when they are of class HTMLEscapedString
"""



# FIXME: Missing: A template loader for this ...

from django.core.template import Template, Lexer, DebugLexer, Parser, DebugParser, VariableNode, DebugVariableNode, StringOrigin
from django.utils.html import escape, linebreaks
from django.conf.settings import DEFAULT_CHARSET, TEMPLATE_DEBUG
from django.core.template.loader import find_template_source


class HTMLTemplate (Template):
    def __init__(self, template_string, origin=None):
        "Compilation stage"
        if TEMPLATE_DEBUG and origin == None:
            origin = StringOrigin(template_string)
            # Could do some crazy stack-frame stuff to record where this string
            # came from...
        self.nodelist = html_compile_string(template_string, origin)

class HTMLParser(Parser):
    def create_variable_node(self, filter_expression):
	return HTMLVariableNode(filter_expression)

class DebugHTMLParser(DebugParser):
    def create_variable_node(self, contents):
        return DebugHTMLVariableNode(contents)

class HTMLVariableNode(VariableNode):
    def encode_output(self, output):
	if isinstance(output, HTMLEscapedString):
	    return output.encode(DEFAULT_CHARSET)
	else:
	    return linebreaks(escape(super(HTMLVariableNode).encode_output(self, output)))

class DebugHTMLVariableNode(DebugVariableNode):
    def encode_output(self, output):
	if isinstance(output, HTMLEscapedString):
	    return output.encode(DEFAULT_CHARSET)
	else:
	    return linebreaks(escape(DebugVariableNode.encode_output(self, output)))

class HTMLEscapedString (unicode):
    """Same as unicode, but HTMLVariableNode does not html-escape instants of
    HTMLEscapedString
    """
    pass

if TEMPLATE_DEBUG:
    lexer_factory = DebugLexer
    parser_factory = DebugHTMLParser
else:
    lexer_factory = Lexer
    parser_factory = HTMLParser

def html_compile_string(template_string, origin):
    "Compiles template_string into NodeList ready for rendering"
    lexer = lexer_factory(template_string, origin)
    parser = parser_factory(lexer.tokenize())
    return parser.parse()

def get_template_from_string(source, origin=None):
    return HTMLTemplate(source, origin)

def get_template(template_name):
    return get_template_from_string(*find_template_source(template_name))


if __name__=='__main__':
    from django.core.template import Context
    TEMPLATE_DEBUG=True
    t = HTMLTemplate(""""
    Dies ist ein Test. 
    {{ s1 }}
    {{ s2 }}
    """)

    c = Context({'s1': u'<b>blabla</b>\n\nboblo&auch',
		 's2': HTMLEscapedString(u'<b>nochwas</b>\n\nblo&amp; test')})
    try:
	print t.render(c)
    except:
	import pdb, sys
	pdb.post_mortem(sys.exc_info()[2])

Reply via email to