Hi,

I'd like to revive the discussion about autoescape (note that it is
*not* on by default). I have brought the patches up to date (see the
notes in the ticket, #2359), and I'm starting to use this now in my
own projects (with the exception of the admin patch which I have no
use for). I can only report that it works great--thanks, Malcolm!

It currently lacks newforms support, but I don't expect any problems
with it. You basically have to wrap mark_safe around the strings
that represent rendered html code. newforms are only a bit moving
around too fast to get proper hold of ;-)

--> http://code.djangoproject.com/ticket/2359

Cheers,

Michael


Malcolm Tredinnick:
> I have put an initial version of the auto-escaping patch I mentioned
> yesterday into ticket #2359. I'll briefly describe what it does below.
> The patch includes changes to the core and a test suite for the
> auto-escaping changes (which is about half the patch).
> 
> My reason for posting this first pass is that there are a few issues
> that have come up that I would like to get some consensus on now, rather
> than after I have ported the rest of the core over to use this stuff. If
> I need to change some things, this is the easiest time to do it. There
> is no documentation patch in this pass because, again, I don't really
> feel like having to re-edit practically the whole doc change if we
> decide to rename some things. This email acts as a documentation proxy
> for the moment.
> 
> The whole implementation is very close to Simon Willison's original
> proposal [1]. With one exception, I have only modified it where there
> were technical requirements to do so. I'm going to assume familiarity
> with that throughout. His proposal really is very good and it seems to
> meet all the sensible requirements brought up in the three threads
> listed at the bottom of that page (the two older threads are probably
> more informative than the most recent one, for those wanting to get up
> to speed here).
> 
> [1] http://code.djangoproject.com/wiki/AutoEscaping
> 
> A summary of the points I'd like opinions on is at the end of the email.
> 
> What does this add?
> -------------------
> (1) An "autoescape" template tag that turns automatic escaping on or off
> throughout its scope.
> 
> (2) A "noescape" filter that marks its result as safe for use without
> further escaping (see the description of "safe strings" below).
> 
> (3) SafeContext and SafeRequestContext classes that act like Context and
> RequestContext, except that they automatically enable auto-escaping in
> the templates they are applied to (you can also set context.autoescape
> on any Context-derived instance, just as in Simon's proposal).
> 
> (4) A "mark_safe()" method to mark strings as not requiring further
> escaping.
> 
> How does it work?
> -----------------
> When a variable is evaluated in a context in a template, it is
> considered to be either "safe" or not (Simon used the term "escaped",
> but that seemed less universally true than "safe"). By default, strings
> are not marked as safe.
> 
> When automatic escaping is enabled, either because {% autoescape on %}
> is in effect, or because a SafeContext class is being used, all strings
> that are not marked as safe are escaped at rendering time (here,
> "escaped" means "conservative HTML escaping": &, <, >, " and ' are
> converted to entities always).
> 
> Any string marked as safe (or passed through the "noescape" filter) is
> not automatically escaped.
> 
> When automatic escaping is disabled in the template, all variable
> results are output without further escaping, unless the "escape" filter
> is applied to them (this is the same behaviour as currently in Django).
> 
> Because some filters are designed to return raw markup, the mark_safe()
> function exists so that the returned strings can be designated as safe.
> For example, {{ var|markdown }} returns raw HTML and the result is not
> subject to any further auto-escaping.
> 
> Some filters (e.g. unordered_list) wrap HTML around raw content. If
> auto-escaping is enabled, these filters will escape the content before
> wrapping it in the HTML tags (the returned result is a safe string in
> all cases). So such filters are auto-escaping-aware.
> 
> Filters that accept text strings as input and return text strings are
> marked (with the "is_safe" attribute) as to whether or not they return a
> safe string whenever they are passed a safe string as input. This has
> the effect of preserving "safeness" for those filters. Note that this
> attribute is a *guarantee* of preserving safeness, so a filter like
> "cut" has is_safe = False: {{ var|cut:"&" }} could turn an escaped
> string into a monster. If a safe string is passed into a filter that is
> not marked as safe and auto-escaping is enabled, the resulting string
> will be escaped. If the is_safe attribute is not attached to a function,
> it is assumed to be not safe.
> 
> Because of the is_safe attribute, it will be possible to change the
> automatically generated documentation in the admin interface to annotate
> each filter with it's "safeness" guarantee.
> 
> The "noescape" filter acts as a way to annotate the result of a filter
> chain as safe. So, although "cut" is not a safe filter, we know that
> cut:"x" is safe (it can't harm our HTML-escaped strings) and thus
> {{ var|cut:"x"|noescape }} will prevent further escaping of the result,
> even in auto-escaping-enabled situations. The "noescape" filter does
> nothing except mark the result as safe -- the string output is identical
> to the input.
> 
> Is it backwards compatible?
> ---------------------------
> Mostly.
> 
> Auto-escaping is not turned on by default (Adrian made a statement in
> [2] and I'm going with that preference at the moment). If you pass a
> normal Context or Context-derived class into a template and do not use
> the autoescape tag, it will be very close to what happens today.
> 
> [2]
> http://groups.google.com/group/django-developers/msg/5a57f37667e1e941?
> 
> 
> Four filters had their behaviour slightly changed.
> 
> Three of these are: linebreaks, linebreaksbr and linenumbers. All three
> now respect the current auto-escaping setting on their input content
> (before applying breaks or numbering). Previously, linenumbers would
> always escape and linebreaks and linebreaksbr would never escape. So,
> the main change for somebody not enabling auto-escaping here is that the
> linenumbers filter will not escape the output any longer.
> 
> The fourth filter is "escape". To make forward porting easier and so
> that template designers do not have to feel restricted in their use of
> the escape filter, I implemented it so that applying "escape" to a safe
> string has no effect. Since "escape" itself makes the result safe,
> applying escape multiple times in a chain has the same effect as
> applying it exactly once.
> 
>         Previously (var = "&"): {{ var|escape|escape }} => &amp;amp;
>         Now: {{ var|escape|escape }} => &amp;
> 
> This particular case of chaining "escape" is obviously not common (I
> would hope).
> 
> All of the default filters (template/defaultfilters.py) and the markup
> filters have been ported in this patch. I have not done anything else
> under contrib/ or the i18n filters.
> 
> Points to note
> --------------
> (1) Because "is_safe" has to be valid for all arguments, the "pluralize"
> filter is not safe at the moment. The bizarre {{ var|puralize:"&" }} is
> an example of the problem case. I'm thinking of fixing this so that we
> check for unsafe characters in the argument(s) and then return safe
> strings on safe input and no unsafe args.
> 
> (2) Because of the way "noescape" works, it was not really possible to
> make {% filter noescape %} work in an auto-escaping block (the contents
> were escaped long before the filter tag was applied). Fortunately, this
> particular filter tag construct is equivalent to {% autoescape off %},
> so there's no functionality loss. A TemplateSyntaxError is raised if the
> illegal construct is used.
> 
> (3) Filters that take non-string arguments (e.g. "join") or return
> something other than a string (e.g. "length") have is_safe = False. This
> is convention more than requirement, but it makes things explicit.
> 
> Performance impact
> -------------------
> Obviously we are doing a little bit more work here, even in the
> non-auto-escaping paths (just testing what the auto-escape setting is,
> for example). As far as I can work out, the performance impact is very
> minor, but I do not have a really good performance test suite for this
> at the moment.
> 
> One simple test: running the tests/othertests/template.py file 100 times
> takes 21.0436 seconds before these changes and 21.1674 seconds
> afterwards -- averaged over five runs on my desktop machine. This tests
> the "no escaping" path. That's a slowdown 0.6% (and that was almost
> within the "noise" of the various runs). These tests aren't particularly
> comprehensive, but they do test the templating code a reasonable amount
> (although not the filters very much at all).
> 
> What are the issues at the moment?
> ----------------------------------
> Now we get to the things I want to sort out before going much further.
> 
> (1) Any violent (or even just passionate) objections to using terms like
> "safe" and mark_safe()?
>         - Should we use Simon's original proposal of escaped and
>         mark_escaped()? I feel "safe" is a bit more consistent with the
>         behaviour (an opposite-but-similar term to Perl's "tainted").
> 
> (2) Is the new behaviour of "escape" reasonable (i.e. it does nothing on
> safe strings)?
>         - The only drawback of this is that there is no way to give an
>         escaped version of a safe string in the templates. That is,
>         there is no opposite to the "noescape" filter.
>         
>         - If we make "escape" apply to safe strings as well, then views
>         must be very consistent about variables always having the same
>         "safeness" state. Otherwise, the template would have to escape
>         sometimes and not escape other times and it has no way of
>         knowing when. The current implementation lets you whack an
>         escape filter on there and it will work always.
>         
>         - Current behaviour also makes forward porting easier (you don't
>         have to run around removing all the escape filters in your code
>         immediately).
>         
> (3) Auto-escaping inherits down through template inclusions. That is, if
> you extend a template that has auto-escaping enabled, you get
> auto-escaping enabled (obviously the autoescape template tag can control
> this). Anybody have a strong reason not to do this?
>         - Personally, I think this is a no-brainer, but I've been wrong
>         plenty of times before.
>         
> (4) Should generic views use SafeContext by default?
>         - I haven't touched this yet, but it's not an insane idea. I
>         guess most people will divide along the same lines as those
>         wanting auto-escaping on or off by default. The waverers will be
>         those favouring consistency over all. I'm not a big enough
>         generic views user to really have a vote in this one.
>         
> (5) Adrian, Jacob: do you guys still want "off by default"?
>         - I *really* don't care what the answer is here, but I would
>         rather not have to change things after porting everything under
>         contrib/ .
>         
>         - For people thinking it's auto-escaping or nothing, {%
>         autoescape on %} at the beginning of a template (and {%
>         endautoescape %}) at the end is not a huge imposition.
>         
> Feedback obviously welcome and appreciated.
> 
> Regards,
> Malcolm
> 
> 
> > 


-- 
noris network AG - Deutschherrnstraße 15-19 - D-90429 Nürnberg -
Tel +49-911-9352-0 - Fax +49-911-9352-100

http://www.noris.de - The IT-Outsourcing Company

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to