textual substitution in an html template by ${varName} notation - javascript

so I was looking at a project and I noted that they had a templating system set up in html files, and I am not too familiar with the whole concept...But when I started browsing the code I was seeing things like: ${varName} which upon execution were being substituted for names out of an nls file which I assume is intended to allow for multiple languages.
I know for a fact that the templating file does not get parsed by a php engine, so I am thinking that maybe the syntax is some type of shorthand for server-side javascript. Which has me intrigued, does anyone have any ideas as to how they are accomplishing this substitution? I cant seem to find info on this in any google search I could think of, so any hints would be helpful.

If you are looking at code which extends dijit._Templated and references a file or an inline string with this syntax, it's being parsed client side. The references are variable names on the widget JS object, which can be set up to point at strings from a localized string bundle with dojo.i18n

Related

Angular $sce vs HTML in external locale files

A question regarding ng-bind-html whilst upgrading an Angular app from 1.0.8 to 1.2.8:
I have locale strings stored in files named en_GB.json, fr_FR.json, etc. So far, I have allowed the use of HTML within the locale strings to allow the team writing the localized content to apply basic styling or adding inline anchor tags. This would result in the following example JSON:
{
"changesLater": "<strong>Don't forget</strong> that you can always make changes later."
"errorEmailExists": "That email address already exists, please sign in to continue."
}
When using these strings with ng-bind-html="myStr", I understand that I now need to use $sce.trustAsHtml(myStr). I could even write a filter as suggested in this StackOverflow answer which would result in using ng-bind-html="myStr | unsafe".
Questions:
By doing something like this, is my app now insecure? And if so, how might an attacker exploit this?
I can understand potential exploits if the source of the displayed HTML string was a user (ie. blog post-style comments that will be displayed to other users), but would my app really be at risk if I'm only displaying HTML from a JSON file hosted on the same domain?
Is there any other way I should be looking to achieve the marking-up of externally loaded content strings in an angular app?
You are not making your app any less secure. You were already inserting HTML in your page with the old method of ng-bind-html-unsafe. You are still doing the same thing, except now you have to explicitly trust the source of the HTML rather than just specifying that part of your template can output raw HTML. Requiring the use of $sce makes it harder to accidentally accept raw HTML from an untrusted source - in the old method where you only declared the trust in the template, bad input might make its way into your model in ways you didn't think of.
If the content comes from your domain, or a domain you control, then you're safe - at least as safe as you can be. If someone is somehow able to highjack the payload of a response from your own domain, then your security is already all manner of screwed. Note, however, you should definitely not ever call $sce.trustAsHtml on content that comes from a domain that isn't yours.
Apart from maintainability concerns, I don't see anything wrong with the way you're doing it. Having a ton of HTML live in a JSON file is maybe not ideal, but as long as the markup is reasonably semantic and not too dense, I think it's fine. If the markup becomes significantly more complex, I'd consider splitting it into separate angular template files or directives as needed, rather than trying to manage a bunch of markup wrapped in JSON strings.

Include javascript file in Node.js without require('..') ing

jade permits you to simply write
include folder/file
to include code from another file.
Is it possible to add simply cut - copy style code from another file in node for javascript files?
Its for development purpose, to isolate some code and work on it seperately.
PS:- I'm aware of require('jsfile.js') and export.x = function(){..
The accepted answer is wrong.
Depending on whether node fs and eval were available at the time this question was written, the accepted answer was probably always wrong.
While not recommended, what you want to do is essentially possible:
Use node's built-in filesystem functions to read the file you want to "copy-paste" into the current file.
Use eval() to "paste" that file into your current file and run it as if it was part of the current file.
https://github.com/dennishall/node-require-without-require
Update 6 Oct 2020: Embarrassingly, the answer I've provided below is false.
I am not certain what were the circumstances for my writings below, as I was familiar with eval at the time (and a very long time before then), however, it is what it is :)
Read the answer that #Dennis wrote for the correct one.
You cannot merge (or include) a script file into another script file during runtime. Utilizing require is your best option to separate your application logic into multiple files.
JavaScript is an object oriented language, and what you are asking for is a solution to a problem that exists in procedural programming languages.
I suggest that you design your application in such a way that would allow you to separate its files into object types that take on different responsibilities instead of treating each file as a script within some global state.
To answer your other question, Jade is actually parsing its source files and therefore can provide its own file merging. If we apply this to our scenario, Jade is to jade source files as V8 is to JavaScript source files. Since the jade language is procedural, it makes sense to allow this kind of feature where in JavaScript (which is object oriented) it doesn't.

Generating code vs file format

So my friend and I had an argument that we couldn't resolve. He is writing a general purpose web game library and a map editor. The map editor saves maps as XML, but the map editor can also load a Lua script that exports the details of the map into a Javascript file that looks something like this(he didn't want to post the code, so this is just a snippet with the names changed):
// This probably isn't valid code, but this is the idea of the code generator
(function() {
Game.Level1 = function (state) {
GameEngine.Group.call(this);
var Object0 = new Game.Lo(new GameEngine.Point(654 , 975.13), 15, state);
var slot123 = new GameEngine.TimeSlot(123); //Start
slot123.addEvent(new GameEngine.Event(Object0, "x", "current", 15, 200));
...
The idea is that the game library would just run this code instead of having to parse a map file and generate objects on the fly. And the Lua script in the map editor that generates the code could be modified by anyone who wanted to output code in a different language for a different library. (not limited to scripting languages).
I've never heard of this idea, usually i'd expect the map data to be in a standard format like JSON or XML and have the game library parse it.
So given that his library is written in javascript and his map can generate javascript to load files, what are the tradeoffs between running the generated code vs parsing JSON/XML and generating objects from that?
In a generic sense loading the metadata from another script, can give added flexibility to the script generator about how the data is sent, displayed etc. For example, you can have complete math expressions, conditionals etc as the part of the loaded script, that will be parsed and loaded seamlessly by the script parser(interpreter). It might be harder to do the same thing by using XML or JSON ( imagine sending an expression to do Miller Cylindrical Projection via XML, on the fly).
I've seen many situations where the app creates its own scripting language (MAXscript, MEL for Maya) to provide flexibility to the user. These are probably not analogous to your friend's usage of Java script to load metadata. But IMHO, it is a continuous spectrum, starting from metadata text files, to XML,JSON, expression parsing, to full fledged script parsing.
On the other hand, sending complicated scripts, will mean exposing part your code base. Also everyone knows what XML does, and you can expect a non-programmer to use/modify XML files. They are comfortable doing it. They may not be comfortable even reading what they think of as 'programs' or 'scripts'. I've seen this first hand in my company, where the artists were uneasy modify a Lua file. They were comfortable modifying the same information, if it was a simple text file. There might some security issues as well, but I'm really not that familiar with it, so I can't comment.

Passing a JSON object to a remote LESS compiler to use as LESS variables

I have an admin panel where users customize the look of a static website (mostly fonts and colors). This panel generate a JSON object with the user values. What I would need to do is passing this JSON to the LESS compiler, so that it can dynamically generate a CSS file from a LESS one using the JSON content as LESS variables. The filename should be different every time, something line file-ID.css (the ID is for the user and it could be passed via JSON too).
Is it technically possible (without extending LESS)? I noticed, for example, that you can pass functions to the parser object when you create it, could I use this functions to evaluate the JSON and passing the variables to the compiler?
Obviously I don't need to know the details, just if it is doable and possibly some link to related information if you have it.
Thanks in advance.
The best way I've found to do what I was trying to accomplish was to use a server side LESS library like PHPLESS to parse the variables from the JSON before compiling. Regular LESS compiler doesn't allow to dynamically inject variables.
To my knowledge the LESS compiler doesn't support any other input than LESS. It would be trivial to make your own pre-parser that mixes-in the variables from JSON .. not even a parser, more of a string-replacer.

Passing Python Data to JavaScript via Django

I'm using Django and Apache to serve webpages. My JavaScript code currently includes a data object with values to be displayed in various HTML widgets based on the user's selection from a menu of choices. I want to derive these data from a Python dictionary. I think I know how to embed the JavaScript code in the HTML, but how do I embed the data object in that script (on the fly) so the script's functions can use it?
Put another way, I want to create a JavaScript object or array from a Python dictionary, then insert that object into the JavaScript code, and then insert that JavaScript code into the HTML.
I suppose this structure (e.g., data embedded in variables in the JavaScript code) is suboptimal, but as a newbie I don't know the alternatives. I've seen write-ups of Django serialization functions, but these don't help me until I can get the data into my JavaScript code in the first place.
I'm not (yet) using a JavaScript library like jQuery.
n.b. see 2018 update at the bottom
I recommend against putting much JavaScript in your Django templates - it tends to be hard to write and debug, particularly as your project expands. Instead, try writing all of your JavaScript in a separate script file which your template loads and simply including just a JSON data object in the template. This allows you to do things like run your entire JavaScript app through something like JSLint, minify it, etc. and you can test it with a static HTML file without any dependencies on your Django app. Using a library like simplejson also saves you the time spent writing tedious serialization code.
If you aren't assuming that you're building an AJAX app this might simply be done like this:
In the view:
from django.utils import simplejson
def view(request, …):
js_data = simplejson.dumps(my_dict)
…
render_template_to_response("my_template.html", {"my_data": js_data, …})
In the template:
<script type="text/javascript">
data_from_django = {{ my_data }};
widget.init(data_from_django);
</script>
Note that the type of data matters: if my_data is a simple number or a string from a controlled source which doesn't contain HTML, such as a formatted date, no special handling is required. If it's possible to have untrusted data provided by a user you will need to sanitize it using something like the escape or escapejs filters and ensure that your JavaScript handles the data safely to avoid cross-site scripting attacks.
As far as dates go, you might also want to think about how you pass dates around. I've almost always found it easiest to pass them as Unix timestamps:
In Django:
time_t = time.mktime(my_date.timetuple())
In JavaScript, assuming you've done something like time_t = {{ time_t }} with the results of the snippet above:
my_date = new Date();
my_date.setTime(time_t*1000);
Finally, pay attention to UTC - you'll want to have the Python and Django date functions exchange data in UTC to avoid embarrassing shifts from the user's local time.
EDIT : Note that the setTime in javascript is in millisecond whereas the output of time.mktime is seconds. That's why we need to multiply by 1000
2018 Update: I still like JSON for complex values but in the intervening decade the HTML5 data API has attained near universal browser support and it's very convenient for passing simple (non-list/dict) values around, especially if you might want to have CSS rules apply based on those values and you don't care about unsupported versions of Internet Explorer.
<div id="my-widget" data-view-mode="tabular">…</div>
let myWidget = document.getElementById("my-widget");
console.log(myWidget.dataset.viewMode); // Prints tabular
somethingElse.addEventListener('click', evt => {
myWidget.dataset.viewMode = "list";
});
This is a neat way to expose data to CSS if you want to set the initial view state in your Django template and have it automatically update when JavaScript updates the data- attribute. I use this for things like hiding a progress widget until the user selects something to process or to conditionally show/hide errors based on fetch outcomes or even something like displaying an active record count using CSS like #some-element::after { content: attr(data-active-transfers); }.
For anyone who might be having a problems with this, be sure you are rendering your json object under safe mode in the template. You can manually set this like this
<script type="text/javascript">
data_from_django = {{ my_data|safe }};
widget.init(data_from_django);
</script>
As of mid-2018 the simplest approach is to use Python's JSON module, simplejson is now deprecated. Beware, that as #wilblack mentions you need to prevent Django's autoescaping either using safe filter or autoescape tag with an off option. In both cases in the view you add the contents of the dictionary to the context
viewset.py
import json
def get_context_data(self, **kwargs):
context['my_dictionary'] = json.dumps(self.object.mydict)
and then in the template you add as #wilblack suggested:
template.html
<script>
my_data = {{ my_dictionary|safe }};
</script>
Security warning:
json.dumps does not escape forward slashes: an attack is {'</script><script>alert(123);</script>': ''}. Same issue as in other answers. Added another answer hopefully fixing it.
You can include <script> tags inside your .html templates, and then build your data structures however is convenient for you. The template language isn't only for HTML, it can also do Javascript object literals.
And Paul is right: it might be best to use a json module to create a JSON string, then insert that string into the template. That will handle the quoting issues best, and deal with deep structures with ease.
It is suboptimal. Have you considered passing your data as JSON using django's built in serializer for that?
See the related response to this question. One option is to use jsonpickle to serialize between Python objects and JSON/Javascript objects. It wraps simplejson and handles things that are typically not accepted by simplejson.
Putting Java Script embedded into Django template is rather always bad idea.
Rather, because there are some exceptions from this rule.
Everything depends on the your Java Script code site and functionality.
It is better to have seperately static files, like JS, but the problem is that every seperate file needs another connect/GET/request/response mechanism. Sometimes for small one, two liners code os JS to put this into template, bun then use django templatetags mechanism - you can use is in other templates ;)
About objects - the same. If your site has AJAX construction/web2.0 like favour - you can achieve very good effect putting some count/math operation onto client side. If objects are small - embedded into template, if large - response them in another connection to avoid hangind page for user.
Fixing the security hole in the answers by #willblack and #Daniel_Kislyuk.
If the data is untrusted, you cannot just do
viewset.py
def get_context_data(self, **kwargs):
context['my_dictionary'] = json.dumps(self.object.mydict)
template.html
<script>
my_data = {{ my_dictionary|safe }};
</script>
because the data could be something like
{"</script><script>alert(123);</script>":""}
and forward slashes aren't escaped by default. Clearly the escaping by json.dumps may not 100% match the escaping in Javascript, which is where the problems come from.
Fixed solution
As far as I can tell, the following fixes the problem:
<script>
my_data = JSON.parse("{{ my_dictionary|escapejs }}");
</script>
If there are still issues, please post in the comments.

Categories

Resources