Edgewall Software
Modify

Opened 14 years ago

Closed 14 years ago

Last modified 14 years ago

#9396 closed defect (fixed)

[PATCH] Data that are passed to `add_script_data` are escaped by Genshi

Reported by: Jun Omae Owned by: Jun Omae
Priority: normal Milestone: 0.12
Component: rendering Version: 0.12dev
Severity: normal Keywords: javascript
Cc: Branch:
Release Notes:
API Changes:
Internal Changes:

Description

The Data that are passed to add_script_data are escaped by Genshi.

Code;

    add_script_data(req, {'test': '&<>"\''})

Result in html;

    <script type="text/javascript"> 
      var test="&amp;&lt;&gt;\"'";
    </script> 

The two values are not the same.

I think that to_json() should encode &, < and > to \u0026, \u003c and \u003e. And these characters are not escaped by Genshi. javascript_quote() has the same issue.

attachment:javascript-genshi.diff

Attachments (4)

javascript-genshi.diff (5.2 KB ) - added by Jun Omae 14 years ago.
test-var.png (5.5 KB ) - added by Jun Omae 14 years ago.
9396-js-escape-r9816.patch (8.6 KB ) - added by Remy Blank 14 years ago.
Fixed an issue with query field labels, refactored.
9396-js-escape-r9821.patch (9.1 KB ) - added by Remy Blank 14 years ago.
Introduce separate $.format() and $.htmlformat().

Download all attachments as: .zip

Change History (19)

by Jun Omae, 14 years ago

Attachment: javascript-genshi.diff added

comment:1 by Remy Blank, 14 years ago

Yes, they are escaped by Genshi, but the resulting string in JavaScript is still correct IIRC, as they are expanded by the browser when parsing the page (they are not in a CDATA section).

Do you actually have a use case for add_script_data() where a string is not passed correctly (i.e. intact) to JavaScript?

by Jun Omae, 14 years ago

Attachment: test-var.png added

comment:2 by Jun Omae, 14 years ago

I don't have any use cases, but it's able to confirm the issue.

Add the below code;

    add_script_data(req, {'test': '&<>"\''})

Then input javascript:alert(test) to the location bar in your browser.

I expect that the below text is shown.

&<>"'

comment:3 by Remy Blank, 14 years ago

Owner: set to Remy Blank

Ok, I thought I had tested this, but obviously I didn't quite succeed :) Could it be browser-specific? Anyway, I'll look into it.

comment:4 by Jun Omae, 14 years ago

I think it isn't browser-specific. I tried in some browsers, the same happens in IE7, Firefox 3.6, Google Chrome 5, Safari 4 and Opera 10.

by Remy Blank, 14 years ago

Attachment: 9396-js-escape-r9816.patch added

Fixed an issue with query field labels, refactored.

comment:5 by Remy Blank, 14 years ago

The patch above is slightly refactored and fixes an issue with query field labels:

  • Moved escaping out of $.template(), as that function is generic and can be used for other purposes than generating HTML to be passed to $().
  • Escaped the text passed to createLabel().
  • Simplified a few expressions.

All tests pass (including the new ones), and working with ticket fields whose names and values contain "≠&" characters seems to work well in the custom query.

Would you mind testing the updated patch? Thanks.

in reply to:  5 comment:6 by Christian Boos, 14 years ago

Replying to rblank:

The patch above is slightly refactored and fixes an issue with query field labels:

  • Moved escaping out of $.template(), as that function is generic and can be used for other purposes than generating HTML to be passed to $().

… but is it really used for something else? I added it for that purpose only and don't expect that we would create HTML piecewise (i.e. pass HTML fragments as template parameters). If the name sounds too generic, we can use htmltemplate instead. Having to add explicitly htmlEscape to all parameters like you do in the patch doesn't feel optimal.

comment:7 by Remy Blank, 14 years ago

The name is misleading, then. Also, that's what made me notice the missing escaping in createLabel(). But yeah, it's more typing, and prone to being forgotten.

About not creating HTML piecewise, we do it in Python (although mainly for translations), so I'd expect that to be useful in JavaScript as well at some point. Speaking of that, shouldn't babel.translate() also escape its arguments? My feeling is yes, except when we do want to insert HTML fragments. Maybe we should escape %s arguments, and have a separate %h format string for non-escaped HTML fragments?

Having said that, we could just have both $.template() and $.htmltemplate() (or just $.html(), even shorter), and use the latter instead of string concatenation in createLabel(). And maybe even rename $.template() to $.format() for consistency.

I'll update the patch shortly.

in reply to:  7 comment:8 by Christian Boos, 14 years ago

Replying to rblank:

Having said that, we could just have both $.template()

Yes, better keep it anyway unchanged, for backwards compatibility.

and $.htmltemplate() (or just $.html(), even shorter)

$.html() would be too easily confused with $().html.

even rename $.template() to $.format() for consistency.

Yes, why not, $.format and $.htmlformat, with template kept as a backward compatibility alias for format.

comment:9 by Remy Blank, 14 years ago

Ok. What about babel.format()?

comment:10 by Christian Boos, 14 years ago

I'm not that fluent in Javascript, but I wonder if we couldn't find a similar approach to the Genshi Markup trick (special "subclass" of String that wouldn't be escaped). That way, we don't need to do anything special in the common case, but we would still have a possibility to pass markup when we really need it. Failing to do that, "%h" would be my fine as well.

by Remy Blank, 14 years ago

Attachment: 9396-js-escape-r9821.patch added

Introduce separate $.format() and $.htmlformat().

comment:11 by Remy Blank, 14 years ago

The patch above has been updated according to comment:8.

About babel.format(), on second thought I don't think we should do any automatic escaping there, as its result is sometimes used as an argument to $.htmlformat(), where it would be escaped a second time. So I'd rather leave it as-is, and add explicit escaping if necessary.

Ok to apply?

comment:12 by Christian Boos, 14 years ago

Two last nit picks: I've seen that every other methods we already have are capitalized, so we should use htmlFormat to be consistent. And we could avoid creating an identify function each time:

  • trac/htdocs/js/trac.js

    diff --git a/trac/htdocs/js/trac.js b/trac/htdocs/js/trac.js
    a b  
    8383  function format(str, args, escape) {
    8484    var kwargs = args[args.length - 1];
    8585    return str.replace(/\${?(\w+)}?/g, function(_, k) {
     86      var repl;
    8687      if (k.length == 1 && k >= '0' && k <= '9')
    87         return escape(args[k - '0']);
     88        repl = args[k - '0'];
    8889      else
    89         return escape(kwargs[k]);
     90        repl = kwargs[k];
     91      return escape ? escape(repl) : repl;
    9092    });
    9193  }
    9294
    9395  // Expand positional ($1 .. $9) and keyword ($name) arguments in a string.
    9496  // The htmlformat() version HTML-escapes arguments prior to substitution.
    9597  $.format = function(str) {
    96     return format(str, arguments, function(s) { return s; });
     98    return format(str, arguments);
    9799  }
    98100
    99101  $.htmlformat = function(str) {

in reply to:  12 ; comment:13 by Remy Blank, 14 years ago

Resolution: fixed
Status: newclosed

Replying to cboos:

I've seen that every other methods we already have are capitalized, so we should use htmlFormat to be consistent.

I thought that was on purpose :)

And we could avoid creating an identify function each time:

Patch applied (including these two changes) in [9822].

comment:14 by Remy Blank, 14 years ago

Owner: changed from Remy Blank to Jun Omae

in reply to:  13 comment:15 by Christian Boos, 14 years ago

Replying to rblank:

Replying to cboos:

I've seen that every other methods we already have are capitalized, so we should use htmlFormat to be consistent.

I thought that was on purpose :)

No, I just wrote comment:6 after/while reading patches on Mercurial-devel ;-)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Jun Omae.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from Jun Omae to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.