Something good has come out of this: while looking for a workaround I
learned about simplejson.dumps(). So now I've defined my own little helper
JD()
import simplejson
def JD(obj):
return XML(simplejson.dumps(obj,indent=4))
In my view (or controller) I can lump into one variable everything I'm going
to need to pass into my js at render time, e.g.
PT = dict(
updatenow=False,
schartoptions = dict(
type ='bar',
barColor ='green',
chartRangeMin = chartmin,
chartRangeMax = chartmax,
)
## add more objects here ...
)
then put a single line at the top of my js script and reference everything
as part of that namespace, e.g.
<script type="text/javascript">
...
var PT = {{=JD(PT)}};
...
$(#something).sparkline( ..., PT.schartoptions);
...
</script>
The JD(PT) expands to a nicely indented js declaration, e.g.
var PT = {
"updatenow": false,
"schartoptions": {
"chartRangeMin": 0,
"barColor": "green",
"type": "bar",
"chartRangeMax": 1
}
};
What's also cool is that if all or part of that declaration corresponds to
data coming in from a getJSON() loop after the page is loaded, then
everything's already defined and initialized.
This feels like a definite improvement over what I was doing before. Far
less clutter and definitely DRY'er.
Cheers,
Mike
On Sat, Jul 24, 2010 at 9:34 AM, Phyo Arkar <[email protected]>wrote:
> I am also doing more and more in JS for views. Even search engine for
> tables, i am using JQGrid's local search (at latest version if JQGrid).It
> dont need server side at all for search to work, which make it a lot faster
> + lesser hit on server performance.
>
>
> On Sat, Jul 24, 2010 at 7:53 PM, Michael Ellis
> <[email protected]>wrote:
>
>> My bad. It does work. In my earlier attempt to use it I forgot that a
>> for loop variable isn't an object reference when looping over a list of
>> strings. So the value of schartoptions wasn't being altered at all, just
>> the loop variable.
>>
>> I'm still in favor of an alternate operator, though. As it is now, I've
>> moved all my chart options inside the script tag e.g.
>>
>> var schartoptions = {
>> type: 'bar',
>> barColor: 'green',
>> chartRangeMin: '{{=chartmin}}',
>> chartRangeMax: '{{=chartmax}}'
>> };
>>
>> and substitute only the things that have to be determined at run time
>> rather than clutter up my expressions by wrapping them in XML().
>>
>> I'd much rather code in python than js, but I'm beginning to feel that
>> using more js and less python in views makes a lot of sense.
>>
>>
>> Thanks,
>> Mike
>>
>>
>>
>> On Sat, Jul 24, 2010 at 8:40 AM, mdipierro <[email protected]>wrote:
>>
>>> I am confused:
>>> Does this now work?
>>>
>>> {{
>>> schartoptions = """{
>>> type: 'bar',
>>> barColor: 'green',
>>> chartRangeMin: '%d',
>>> chartRangeMax: '%d'
>>> }
>>> """%(chartmin,chartmax)
>>>
>>> }}
>>>
>>> and later on I use the variables within a script tag, e.g.
>>>
>>> <script type="text/javascript">
>>> /* <![CDATA[ */
>>> $("#{{=ks+kc}}").sparkline(data.wsc.{{=ks}}.{{=kc}},
>>> {{=XML(schartoptions)}}
>>> </script>
>>>
>>> If not, what are chartmin and chartmax, are they themselves helpers?
>>>
>>> On Jul 24, 7:28 am, Michael Ellis <[email protected]> wrote:
>>> > Massimo, I'm not following you. I tried using XML (see earlier post)
>>> and it
>>> > had no effect. Does it only work if applied immediately before the =
>>> > operator?
>>> >
>>> > Also, I think ":=" or something similar is much cleaner than wrapping
>>> > everything in a function call.
>>> >
>>> > Cheers,
>>> > Mike
>>> >
>>> > On Sat, Jul 24, 2010 at 8:19 AM, mdipierro <[email protected]>
>>> wrote:
>>> > > This
>>> >
>>> > > {{:=never_escaped}}
>>> >
>>> > > would be the same as
>>> >
>>> > > {{=XML(ever_escaped)}}
>>> >
>>> > > so why introduce new syntax?
>>> >
>>> > > On Jul 24, 7:14 am, Michael Ellis <[email protected]> wrote:
>>> > > > I could happily live with a solution that adds a 'no escape'
>>> operator to
>>> > > the
>>> > > > template language, e.g.
>>> >
>>> > > > {{:=never_escaped}}
>>> >
>>> > > > vs
>>> >
>>> > > > {{=always_escaped}}
>>> >
>>> > > > 1. Backward compatible,
>>> >
>>> > > > 2. Safe by default,
>>> >
>>> > > > 3. Allows designer to decide what's safe and what isn't,
>>> >
>>> > > > 4. Seems like an easier fix than trying to make the rendering code
>>> smart
>>> > > > enough to always distinguish js from html strings.
>>> >
>>> > > > Just a thought,
>>> > > > Mike
>>> >
>>> > > > On Sat, Jul 24, 2010 at 4:02 AM, mdipierro <
>>> [email protected]>
>>> > > wrote:
>>> > > > > Thadeus,
>>> >
>>> > > > > This was a security fix. We had a a security review and this was
>>> > > > > determined to be a weakness. The code by Mike Ellis broke not
>>> because
>>> > > > > of the fix but because it incorrectly implicitly assumed that
>>> the
>>> > > > > strings were HTML/XML and therefore needed escaping when, in
>>> reality,
>>> > > > > they were JS strings.
>>> >
>>> > > > > If we had a review board, would you have opposed to this change?
>>> >
>>> > > > > Massimo
>>> >
>>> > > > > On Jul 23, 5:28 pm, Thadeus Burgess <[email protected]>
>>> wrote:
>>> > > > > > I also agree that this is a break in backwards compatibility.
>>> It is
>>> > > also
>>> > > > > a
>>> > > > > > change that was never considered for longer than 15 minutes
>>> before
>>> > > the
>>> > > > > > decision to make the change was implemented.
>>> >
>>> > > > > > I really wish we would put certain things such as this under a
>>> review
>>> > > > > board
>>> > > > > > so they don't get into web2py and break things!
>>> >
>>> > > > > > --
>>> > > > > > Thadeus
>>> >
>>> > > > > > On Fri, Jul 23, 2010 at 2:33 PM, MikeEllis <
>>> > > [email protected]
>>> > > > > >wrote:
>>> >
>>> > > > > > > Typo: 2 sentence in prior message should read
>>> >
>>> > > > > > > " ... after XML() supplies the unescaped string."
>>> >
>>> > > > > > > On Jul 23, 3:28 pm, Michael Ellis <[email protected]
>>> >
>>> > > wrote:
>>> > > > > > > > Urgh! FWIW, putting XML() around the strings doesn't seem
>>> to
>>> > > work.
>>> > > > > > > Looks
>>> > > > > > > > like the escaping is applied after XML() supplies the
>>> unquoted
>>> > > > > string.
>>> >
>>> > > > > > > > I tried
>>> > > > > > > > {{
>>> > > > > > > > for optstring in (schartoptions, countpieoptions,
>>> cchartoptions):
>>> > > > > > > > optstring = XML(optstring)
>>> > > > > > > > debug("opstring=%s"%optstring)
>>> > > > > > > > pass}}
>>> >
>>> > > > > > > > after assigning the strings and before they are used in
>>> inside
>>> > > the
>>> > > > > > > <script>
>>> > > > > > > > tags.
>>> >
>>> > > > > > > > The debug() calls show the strings with the single quotes
>>> > > unescaped,
>>> > > > > but
>>> > > > > > > > they still end up being escaped in what gets sent to
>>> browser.
>>> >
>>> > > > > > > > On Fri, Jul 23, 2010 at 2:16 PM, Michael Ellis <
>>> > > > > > > [email protected]>wrote:
>>> >
>>> > > > > > > > > Thanks, Nathan. That's certainly a possibility. It's
>>> just that
>>> > > I'm
>>> > > > > not
>>> > > > > > > > > sure what security issue this change actually fixes.
>>> There are
>>> > > no
>>> > > > > > > > > user-supplied strings in what I'm using to generate the
>>> jQuery
>>> > > > > calls.
>>> > > > > > > If
>>> > > > > > > > > that were the case, then yes it would definitely be my
>>> > > > > responsibility
>>> > > > > > > to
>>> > > > > > > > > properly sanitize it.
>>> >
>>> > > > > > > > > Have to say this feels like a loss of backward
>>> compatibility
>>> > > to
>>> > > > > me.
>>> > > > > > > I've
>>> > > > > > > > > got a fair amount of code in this app that uses that
>>> technique;
>>> > > > > it's
>>> > > > > > > already
>>> > > > > > > > > inherently messy because of the indirection involved in
>>> code
>>> > > > > > > generation.
>>> > > > > > > > > Wrapping it all in XML calls just adds to the mess.
>>> Hope
>>> > > there's
>>> > > > > a
>>> > > > > > > way to
>>> > > > > > > > > refine the security fix so that it's confined to the
>>> areas that
>>> > > > > matter.
>>> >
>>> > > > > > > > > Cheers,
>>> > > > > > > > > Mike
>>> >
>>> > > > > > > > > On Fri, Jul 23, 2010 at 1:56 PM, mr.freeze <
>>> > > [email protected]>
>>> > > > > > > wrote:
>>> >
>>> > > > > > > > >> It was probably introduced as a security fix. You can
>>> do:
>>> > > > > > > > >> {{
>>> > > > > > > > >> schartoptions = XML("""{
>>> > > > > > > > >> type: 'bar',
>>> > > > > > > > >> barColor: 'green',
>>> > > > > > > > >> chartRangeMin: '%d',
>>> > > > > > > > >> chartRangeMax: '%d'
>>> > > > > > > > >> }
>>> > > > > > > > >> """%(chartmin,chartmax))
>>> > > > > > > > >> }}
>>> >
>>> > > > > > > > >> and it won't be escaped.
>>> >
>>> > > > > > > > >> On Jul 23, 12:39 pm, Michael Ellis <
>>> [email protected]
>>> >
>>> > > > > wrote:
>>> > > > > > > > >> > I've got an app with views that generate jQuery code
>>> on the
>>> > > fly.
>>> > > > > > > This
>>> > > > > > > > >> was
>>> > > > > > > > >> > all working fine until recently, i.e. sometime after
>>> 1.92.
>>> > > With
>>> > > > > > > more
>>> > > > > > > > >> recent
>>> > > > > > > > >> > builds, single and double quotes in strings are now
>>> escaped
>>> > > and
>>> > > > > it
>>> > > > > > > > >> breaks
>>> > > > > > > > >> > the javascript. Here's an example
>>> >
>>> > > > > > > > >> > The view has (with much snipped out):
>>> >
>>> > > > > > > > >> > {{
>>> > > > > > > > >> > schartoptions = """{
>>> > > > > > > > >> > type: 'bar',
>>> > > > > > > > >> > barColor: 'green',
>>> > > > > > > > >> > chartRangeMin: '%d',
>>> > > > > > > > >> > chartRangeMax: '%d'
>>> > > > > > > > >> > }
>>> > > > > > > > >> > """%(chartmin,chartmax)
>>> >
>>> > > > > > > > >> > }}
>>> >
>>> > > > > > > > >> > and later on I use the variables within a script tag,
>>> e.g.
>>> >
>>> > > > > > > > >> > <script type="text/javascript">
>>> > > > > > > > >> > /* <![CDATA[ */
>>> > > > > > > > >> >
>>> $("#{{=ks+kc}}").sparkline(data.wsc.{{=ks}}.{{=kc}},
>>> > > > > > > > >> {{=schartoptions}}
>>> > > > > > > > >> > </script>
>>> >
>>> > > > > > > > >> > With an earlier web2py, it produces the desired
>>> result,
>>> >
>>> > > > > > > > >> > $("#solution0").sparkline(data.s.solution0, {
>>> > > > > > > > >> > type: 'bar',
>>> > > > > > > > >> > barColor: 'green',
>>> > > > > > > > >> > chartRangeMin: '0',
>>> > > > > > > > >> > chartRangeMax: '1'
>>> > > > > > > > >> > }
>>> > > > > > > > >> > );
>>> >
>>> > > > > > > > >> > but now (at tip) I get
>>> >
>>> > > > > > > > >> > $("#solution0").sparkline(data.s.solution0, {
>>> > > > > > > > >> > type: 'bar',
>>> > > > > > > > >> > barColor: 'green',
>>> > > > > > > > >> > chartRangeMin: '0',
>>> > > > > > > > >> > chartRangeMax: '1'
>>> > > > > > > > >> > }
>>> > > > > > > > >> > );
>>> >
>>> > > > > > > > >> > Was this change intentional? If so, what's the
>>> recommended
>>> > > > > > > workaround?
>>> >
>>> > > > > > > > >> > Thanks,
>>> > > > > > > > >> > Mike
>>>
>>
>>
>