Quantcast

Loading dojo with content security policy (CSP) without unsafe-eval

classic Classic list List threaded Threaded
7 messages Options
amb
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Loading dojo with content security policy (CSP) without unsafe-eval

amb
I would like to load dojo/dijit on a page with a
Content-Security-Policy header that does not include 'unsafe-eval'.

When loading dojo.js from 1.11.1 without unsafe-eval enabled, I see
the following error:

-- copy ---
dojo.js:348 Uncaught EvalError: Refused to evaluate a string as
JavaScript because 'unsafe-eval' is not an allowed source of script in
the following Content Security Policy directive: "script-src 'self'
'unsafe-inline' 'nonce-owFwutk2cD0/WB79vWfsXNlECBAxLaac' ".
hasCache.host-browser @ dojo.js:348(anonymous function) @ dojo.js:1973
test.js:93 Uncaught ReferenceError: require is not defined ...
-- end copy --

The 1.11 release notes have this section:

-- copy --
csp: A feature test, 'has("csp-restrictions")' was added for non-csp
compliant code. Please set this feature test to true in order to run
code that must be csp compliant.
-- end copy --

But I have no idea what this means, does the CSP above refer to
'content-security-policy' ? If so is this a flag somehow I need to
set?  I tried setting this on the <script
data-dojo-config="{csp-restrictions: true}" ..> dojo load statement
but that didn't seem to do anything.  The dojo.js 'var eval_' section
near line dojo.js:348 has a conditional that seems to avoid the eval()
that I'm seeing in the error message, but I don't have any idea how to
trigger the 'has("csp-restrictions")' conditional to make it avoid the
eval().

In my environment I can not modify/compile the dojo release code.

So my questions is: is it possible to use unmodified/compiled
dojo/dijit on a page where the Content-Security-Policy is prohibiting
unsafe-eval() ?

Thanks!
--
Dojo Toolkit: http://dojotoolkit.org/
Tutorials: http://dojotoolkit.org/documentation/

[hidden email]
To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Loading dojo with content security policy (CSP) without unsafe-eval

dylanks
In the current implementation, we had set it to be something that could
be configured for builds, but we were not really thinking this would be
a run-time configurable feature setting. We can revisit that decision.

Meanwhile, you could do something like this:

// app/has.js
define([ 'dojo/has' ], function (has) {
        has.add('csp-restrictions', true);
        return has;
});

And then in your configuration object, you can change the value for map
so that Dojo and other code picks up your extended form of has, except
for your extension module:

map: {
    '*': {
        'dojo/has': 'app/has'
    },
    'app/has': {
        'dojo/has': 'dojo/has'
    }
}

See
https://www.sitepen.com/blog/2013/07/03/dojo-faq-what-is-the-map-config-option/
for more details on map configuration.

Regards,
-Dylan

on 5/22/16, 18:54 (GMT-07:00) Jason Rivard said the following:

> I would like to load dojo/dijit on a page with a
> Content-Security-Policy header that does not include 'unsafe-eval'.
>
> When loading dojo.js from 1.11.1 without unsafe-eval enabled, I see
> the following error:
>
> -- copy ---
> dojo.js:348 Uncaught EvalError: Refused to evaluate a string as
> JavaScript because 'unsafe-eval' is not an allowed source of script in
> the following Content Security Policy directive: "script-src 'self'
> 'unsafe-inline' 'nonce-owFwutk2cD0/WB79vWfsXNlECBAxLaac' ".
> hasCache.host-browser @ dojo.js:348(anonymous function) @ dojo.js:1973
> test.js:93 Uncaught ReferenceError: require is not defined ...
> -- end copy --
>
> The 1.11 release notes have this section:
>
> -- copy --
> csp: A feature test, 'has("csp-restrictions")' was added for non-csp
> compliant code. Please set this feature test to true in order to run
> code that must be csp compliant.
> -- end copy --
>
> But I have no idea what this means, does the CSP above refer to
> 'content-security-policy' ? If so is this a flag somehow I need to
> set?  I tried setting this on the <script
> data-dojo-config="{csp-restrictions: true}" ..> dojo load statement
> but that didn't seem to do anything.  The dojo.js 'var eval_' section
> near line dojo.js:348 has a conditional that seems to avoid the eval()
> that I'm seeing in the error message, but I don't have any idea how to
> trigger the 'has("csp-restrictions")' conditional to make it avoid the
> eval().
>
> In my environment I can not modify/compile the dojo release code.
>
> So my questions is: is it possible to use unmodified/compiled
> dojo/dijit on a page where the Content-Security-Policy is prohibiting
> unsafe-eval() ?
>
> Thanks!
--
Dojo Toolkit: http://dojotoolkit.org/
Tutorials: http://dojotoolkit.org/documentation/

[hidden email]
To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
Co-Founder, Dojo Toolkit
CEO, SitePen, Inc.  http://www.sitepen.com/
amb
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Loading dojo with content security policy (CSP) without unsafe-eval

amb
On Mon, May 23, 2016 at 7:23 AM, Dylan Schiemann <[hidden email]> wrote:
> In the current implementation, we had set it to be something that could
> be configured for builds, but we were not really thinking this would be
> a run-time configurable feature setting. We can revisit that decision.

Thanks for the reply!

Yes, that would be great.  Doing a 'build' of a javascript library
isn't something I think I'll ever be doing.  I suspect many js library
users are this way for a variety of reasons.

> Meanwhile, you could do something like this:
>
> // app/has.js
> define([ 'dojo/has' ], function (has) {
>         has.add('csp-restrictions', true);
>         return has;
> });
>
> And then in your configuration object, you can change the value for map
> so that Dojo and other code picks up your extended form of has, except
> for your extension module:
>
> map: {
>     '*': {
>         'dojo/has': 'app/has'
>     },
>     'app/has': {
>         'dojo/has': 'dojo/has'
>     }
> }
>
> See
> https://www.sitepen.com/blog/2013/07/03/dojo-faq-what-is-the-map-config-option/
> for more details on map configuration.

Thanks for this suggestion I really appreciate it!   Unfortunately
though I don't understand how dojo works well enough to implement your
suggestion.  The article you reference suggests that you can specify
things to replace(overload?) the standard dojo files/functions, but I
can't understand it much better than that.  I'm also not really clear
on what you mean by 'configuration object' , but I'm guessing that's a
dojoConfig js class defined before the script loads and/or in the
contents of data-dojo-config attribute?  Anyway I tried this:

-- begin copy --
<script type="text/javascript">
        // app/has.js
        define([ 'dojo/has' ], function (has) {
            has.add('csp-restrictions', true);
            return has;
        });
        dojoConfig = {
            map: { '*': { 'dojo/has': 'app/has' }, 'app/has': {
'dojo/has': 'dojo/has' }}
        };

</script>
<script data-dojo-config="{async: true,  map: { '*': {'dojo/has':
'app/has'},'app/has': {'dojo/has': 'dojo/has'}}}"
dojo-sync-loader="false" type="text/javascript"
src="/dojo/dojo/dojo.js"></script>
-- end copy --

But that didn't seem to work, I got the same error as before along
with 'Uncaught ReferenceError: define is not defined', as I guess dojo
defines 'define'.  I tried moving the 'define' script after the dojo
js load but dojo still doesn't load so there's still no define
defined.   This would be good if I could get this working,  the inline
script isn't desirable from a CSP perspective  - but it's better than
unsafe-eval.

Is there a straightforward way to do this? - If so I need specific
instructions :(  Otherwise I think I'm stuck waiting until a runtime
option appears....

> Regards,
> -Dylan
>
 [snip]
--
Dojo Toolkit: http://dojotoolkit.org/
Tutorials: http://dojotoolkit.org/documentation/

[hidden email]
To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Loading dojo with content security policy (CSP) without unsafe-eval

dylanks
See inline...

on 5/23/16, 05:46 (GMT-07:00) Jason Rivard said the following:

> On Mon, May 23, 2016 at 7:23 AM, Dylan Schiemann <[hidden email]> wrote:
>> In the current implementation, we had set it to be something that could
>> be configured for builds, but we were not really thinking this would be
>> a run-time configurable feature setting. We can revisit that decision.
>
> Thanks for the reply!
>
> Yes, that would be great.  Doing a 'build' of a javascript library
> isn't something I think I'll ever be doing.  I suspect many js library
> users are this way for a variety of reasons.
>
>> Meanwhile, you could do something like this:
>>
>> // app/has.js
>> define([ 'dojo/has' ], function (has) {
>>         has.add('csp-restrictions', true);
>>         return has;
>> });
>>
>> And then in your configuration object, you can change the value for map
>> so that Dojo and other code picks up your extended form of has, except
>> for your extension module:
>>
>> map: {
>>     '*': {
>>         'dojo/has': 'app/has'
>>     },
>>     'app/has': {
>>         'dojo/has': 'dojo/has'
>>     }
>> }
>>
>> See
>> https://www.sitepen.com/blog/2013/07/03/dojo-faq-what-is-the-map-config-option/
>> for more details on map configuration.
>
> Thanks for this suggestion I really appreciate it!   Unfortunately
> though I don't understand how dojo works well enough to implement your
> suggestion.  The article you reference suggests that you can specify
> things to replace(overload?) the standard dojo files/functions, but I
> can't understand it much better than that.  I'm also not really clear
> on what you mean by 'configuration object' , but I'm guessing that's a
> dojoConfig js class defined before the script loads and/or in the
> contents of data-dojo-config attribute?  Anyway I tried this:
>
> -- begin copy --
> <script type="text/javascript">
>         // app/has.js
>         define([ 'dojo/has' ], function (has) {
>             has.add('csp-restrictions', true);
>             return has;
>         });
>         dojoConfig = {
>             map: { '*': { 'dojo/has': 'app/has' }, 'app/has': {
> 'dojo/has': 'dojo/has' }}
>         };
>
> </script>

The above block needs to be a separate file (noted by the // app/has.js
comment). app is just whatever top-level package name you use for your
custom code. So if you change it to say foo/has.js, then you would
change app to foo in the block below...

> <script data-dojo-config="{async: true,  map: { '*': {'dojo/has':
> 'app/has'},'app/has': {'dojo/has': 'dojo/has'}}}"
> dojo-sync-loader="false" type="text/javascript"
> src="/dojo/dojo/dojo.js"></script>
> -- end copy --
>
> But that didn't seem to work, I got the same error as before along
> with 'Uncaught ReferenceError: define is not defined', as I guess dojo
> defines 'define'.  I tried moving the 'define' script after the dojo
> js load but dojo still doesn't load so there's still no define
> defined.   This would be good if I could get this working,  the inline
> script isn't desirable from a CSP perspective  - but it's better than
> unsafe-eval.
>
> Is there a straightforward way to do this? - If so I need specific
> instructions :(  Otherwise I think I'm stuck waiting until a runtime
> option appears....
>
>> Regards,
>> -Dylan
>>
>  [snip]
--
Dojo Toolkit: http://dojotoolkit.org/
Tutorials: http://dojotoolkit.org/documentation/

[hidden email]
To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
Co-Founder, Dojo Toolkit
CEO, SitePen, Inc.  http://www.sitepen.com/
amb
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Loading dojo with content security policy (CSP) without unsafe-eval

amb
See inline...

On Mon, May 23, 2016 at 11:51 AM, Dylan Schiemann <[hidden email]> wrote:
> See inline...
>
> on 5/23/16, 05:46 (GMT-07:00) Jason Rivard said the following:
>> On Mon, May 23, 2016 at 7:23 AM, Dylan Schiemann <[hidden email]> wrote:

[snip]

> The above block needs to be a separate file (noted by the // app/has.js
> comment). app is just whatever top-level package name you use for your
> custom code. So if you change it to say foo/has.js, then you would
> change app to foo in the block below...
>
>> <script data-dojo-config="{async: true,  map: { '*': {'dojo/has':
>> 'app/has'},'app/has': {'dojo/has': 'dojo/has'}}}"
>> dojo-sync-loader="false" type="text/javascript"
>> src="/dojo/dojo/dojo.js"></script>
>>
>>  [snip]

Thanks again!  That makes more sense, though since I'm trying to replace code in dojo.js I'm not sure why I'm trying to override has.js.  But I'll take your word for it.

Still no luck though.  Using the exact script tag above, I do not see the browser (chrome or firefox) attempt to load app/has.js.   dojo/has.js is always loaded though.   I also tried removing the wrapping braces '{}' around the data-dojo-config attribute value due to an error I saw at one point and based on the examples at 'https://dojotoolkit.org/documentation/tutorials/1.10/dojo_config/' but that didn't help.   The debugger still goes through the code in var eval_ = has("csp-restrictions") at line 348 (verifying with a breakpoint in chrome debug).  I also tried again with the dojoConfig object defined in an inline script, but same results.  No matter what it seems my dojo config value is ignored or incorrect - I don't know how to debug enough to tell which. 

I created a file /app/has.js that is a peer to /dojo/dojo.js with the contents:

define([ 'dojo/has' ], function (has) {
    has.add('csp-restrictions', true);
    return has;
});

But since it's never loaded, I don't think it matters yet.  I tired loading it with a <script src> reference before and after dojo but theres still the same chicken/egg with define not being defined.   I tried all the above with the CSP header disabled, so it shouldn't be impacting the dojo load.  Other code I have that uses dojo functionality like Dialog seems to work fine so dojo is definitely loading.

I'm probably missing something obvious, but since I have no clue what I'm doing and just trying things at random I don't think I'm going to figure it out this way.  Any other suggestions?  Is there someway to get some debug logging that would be helpful?  I tried setting 'isDebug: true' via the above methods as well but that doesn't seem to change the browser log output, is there any way to get dojo to output its config on startup so I can see if the dojoConfig is even being read?

Thanks again!


> --
> Dojo Toolkit: http://dojotoolkit.org/
> Tutorials: http://dojotoolkit.org/documentation/
>
> [hidden email]
> To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest

--
Dojo Toolkit: http://dojotoolkit.org/
Tutorials: http://dojotoolkit.org/documentation/

[hidden email]
To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Loading dojo with content security policy (CSP) without unsafe-eval

dylanks
I'll try to put a more complete example together for you, but it might
take a few days due to a busy schedule. The main things to keep in mind:

1. The idea is that you want any code that relies on dojo/has to rely on
app/has, except the app/has module itself
2. Your directory structure should by default have the dojo/ and has/
folders as siblings, which I think you have said you've done
3. You might try adding packages do your dojo config (
https://www.sitepen.com/blog/2013/06/20/dojo-faq-what-is-the-difference-packages-vs-paths-vs-aliases/
... use packages, not paths or aliases) and explicitly specify where
dojo and has live
4. You could add a statement the line before the eval_ that basically
says console.log(has("csp-restrictions")); and see what the value of the
feature test returns
5. You should be able to look in the network tab to verify that the
dependency is loaded

Regards,
-Dylan

on 5/23/16, 19:22 (GMT-07:00) Jason Rivard said the following:

> See inline...
>
> On Mon, May 23, 2016 at 11:51 AM, Dylan Schiemann <[hidden email]
> <mailto:[hidden email]>> wrote:
>> See inline...
>>
>> on 5/23/16, 05:46 (GMT-07:00) Jason Rivard said the following:
>>> On Mon, May 23, 2016 at 7:23 AM, Dylan Schiemann
> <[hidden email] <mailto:[hidden email]>> wrote:
>
> [snip]
>
>> The above block needs to be a separate file (noted by the // app/has.js
>> comment). app is just whatever top-level package name you use for your
>> custom code. So if you change it to say foo/has.js, then you would
>> change app to foo in the block below...
>>
>>> <script data-dojo-config="{async: true,  map: { '*': {'dojo/has':
>>> 'app/has'},'app/has': {'dojo/has': 'dojo/has'}}}"
>>> dojo-sync-loader="false" type="text/javascript"
>>> src="/dojo/dojo/dojo.js"></script>
>>>
>>>  [snip]
>
> Thanks again!  That makes more sense, though since I'm trying to replace
> code in dojo.js I'm not sure why I'm trying to override has.js.  But
> I'll take your word for it.
>
> Still no luck though.  Using the exact script tag above, I do not see
> the browser (chrome or firefox) attempt to load app/has.js.  
> dojo/has.js is always loaded though.   I also tried removing the
> wrapping braces '{}' around the data-dojo-config attribute value due to
> an error I saw at one point and based on the examples at
> 'https://dojotoolkit.org/documentation/tutorials/1.10/dojo_config/' but
> that didn't help.   The debugger still goes through the code in var
> eval_ = has("csp-restrictions") at line 348 (verifying with a breakpoint
> in chrome debug).  I also tried again with the dojoConfig object defined
> in an inline script, but same results.  No matter what it seems my dojo
> config value is ignored or incorrect - I don't know how to debug enough
> to tell which.
>
> I created a file /app/has.js that is a peer to /dojo/dojo.js with the
> contents:
>
> define([ 'dojo/has' ], function (has) {
>     has.add('csp-restrictions', true);
>     return has;
> });
>
> But since it's never loaded, I don't think it matters yet.  I tired
> loading it with a <script src> reference before and after dojo but
> theres still the same chicken/egg with define not being defined.   I
> tried all the above with the CSP header disabled, so it shouldn't be
> impacting the dojo load.  Other code I have that uses dojo functionality
> like Dialog seems to work fine so dojo is definitely loading.
>
> I'm probably missing something obvious, but since I have no clue what
> I'm doing and just trying things at random I don't think I'm going to
> figure it out this way.  Any other suggestions?  Is there someway to get
> some debug logging that would be helpful?  I tried setting 'isDebug:
> true' via the above methods as well but that doesn't seem to change the
> browser log output, is there any way to get dojo to output its config on
> startup so I can see if the dojoConfig is even being read?
>
> Thanks again!
>
>
>> --
>> Dojo Toolkit: http://dojotoolkit.org/
>> Tutorials: http://dojotoolkit.org/documentation/
>>
>> [hidden email]
> <mailto:[hidden email]>
>> To unsubscribe, visit:
> http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
>
--
Dojo Toolkit: http://dojotoolkit.org/
Tutorials: http://dojotoolkit.org/documentation/

[hidden email]
To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
Co-Founder, Dojo Toolkit
CEO, SitePen, Inc.  http://www.sitepen.com/
amb
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Loading dojo with content security policy (CSP) without unsafe-eval

amb
See below...

On Mon, May 23, 2016 at 11:57 PM, Dylan Schiemann <[hidden email]> wrote:

> I'll try to put a more complete example together for you, but it might
> take a few days due to a busy schedule. The main things to keep in mind:
>
> 1. The idea is that you want any code that relies on dojo/has to rely on
> app/has, except the app/has module itself
> 2. Your directory structure should by default have the dojo/ and has/
> folders as siblings, which I think you have said you've done
> 3. You might try adding packages do your dojo config (
> https://www.sitepen.com/blog/2013/06/20/dojo-faq-what-is-the-difference-packages-vs-paths-vs-aliases/
> ... use packages, not paths or aliases) and explicitly specify where
> dojo and has live
> 4. You could add a statement the line before the eval_ that basically
> says console.log(has("csp-restrictions")); and see what the value of the
> feature test returns
> 5. You should be able to look in the network tab to verify that the
> dependency is loaded
>
> Regards,
> -Dylan

Thanks again sir.  I spent a few more hours tonight fussing with this
and I still never got anywhere.  I was never able to see my app/has.js
loaded or attempted to be loaded by the browser in the network tab.
The article you linked was helpful in background but I'm still lost on
the specifics.  Coming from a more structured programming background
my brain seems to simply be unable to grok the notion of using
closures to substitute for language-level class/package semantics.
At this point I feel I may be hopeless.   Perhaps your efforts would
be better spent making the enhancement to make this easy for n00bs
like me :)

I filed enhancement request here:  https://bugs.dojotoolkit.org/ticket/18850

Thanks for your help!



> on 5/23/16, 19:22 (GMT-07:00) Jason Rivard said the following:
>> See inline...
>>
>> On Mon, May 23, 2016 at 11:51 AM, Dylan Schiemann <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>> See inline...
>>>
>>> on 5/23/16, 05:46 (GMT-07:00) Jason Rivard said the following:
>>>> On Mon, May 23, 2016 at 7:23 AM, Dylan Schiemann
>> <[hidden email] <mailto:[hidden email]>> wrote:
>>
>> [snip]
>>
>>> The above block needs to be a separate file (noted by the // app/has.js
>>> comment). app is just whatever top-level package name you use for your
>>> custom code. So if you change it to say foo/has.js, then you would
>>> change app to foo in the block below...
>>>
>>>> <script data-dojo-config="{async: true,  map: { '*': {'dojo/has':
>>>> 'app/has'},'app/has': {'dojo/has': 'dojo/has'}}}"
>>>> dojo-sync-loader="false" type="text/javascript"
>>>> src="/dojo/dojo/dojo.js"></script>
>>>>
>>>>  [snip]
>>
>> Thanks again!  That makes more sense, though since I'm trying to replace
>> code in dojo.js I'm not sure why I'm trying to override has.js.  But
>> I'll take your word for it.
>>
>> Still no luck though.  Using the exact script tag above, I do not see
>> the browser (chrome or firefox) attempt to load app/has.js.
>> dojo/has.js is always loaded though.   I also tried removing the
>> wrapping braces '{}' around the data-dojo-config attribute value due to
>> an error I saw at one point and based on the examples at
>> 'https://dojotoolkit.org/documentation/tutorials/1.10/dojo_config/' but
>> that didn't help.   The debugger still goes through the code in var
>> eval_ = has("csp-restrictions") at line 348 (verifying with a breakpoint
>> in chrome debug).  I also tried again with the dojoConfig object defined
>> in an inline script, but same results.  No matter what it seems my dojo
>> config value is ignored or incorrect - I don't know how to debug enough
>> to tell which.
>>
>> I created a file /app/has.js that is a peer to /dojo/dojo.js with the
>> contents:
>>
>> define([ 'dojo/has' ], function (has) {
>>     has.add('csp-restrictions', true);
>>     return has;
>> });
>>
>> But since it's never loaded, I don't think it matters yet.  I tired
>> loading it with a <script src> reference before and after dojo but
>> theres still the same chicken/egg with define not being defined.   I
>> tried all the above with the CSP header disabled, so it shouldn't be
>> impacting the dojo load.  Other code I have that uses dojo functionality
>> like Dialog seems to work fine so dojo is definitely loading.
>>
>> I'm probably missing something obvious, but since I have no clue what
>> I'm doing and just trying things at random I don't think I'm going to
>> figure it out this way.  Any other suggestions?  Is there someway to get
>> some debug logging that would be helpful?  I tried setting 'isDebug:
>> true' via the above methods as well but that doesn't seem to change the
>> browser log output, is there any way to get dojo to output its config on
>> startup so I can see if the dojoConfig is even being read?
>>
>> Thanks again!
>>
>>
>>> --
>>> Dojo Toolkit: http://dojotoolkit.org/
>>> Tutorials: http://dojotoolkit.org/documentation/
>>>
>>> [hidden email]
>> <mailto:[hidden email]>
>>> To unsubscribe, visit:
>> http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
>>
> --
> Dojo Toolkit: http://dojotoolkit.org/
> Tutorials: http://dojotoolkit.org/documentation/
>
> [hidden email]
> To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
--
Dojo Toolkit: http://dojotoolkit.org/
Tutorials: http://dojotoolkit.org/documentation/

[hidden email]
To unsubscribe, visit: http://mail.dojotoolkit.org/mailman/listinfo/dojo-interest
Loading...