I frequently write client side code in the code-behind section of my asp.net applications. I think its about time to get a refresher on how to write client side code on server side page.
I need to refresh mysel fwith the "double quotes" and "single quotes". Not sure what that is called, but can anyone point me to the correct resource where I can learn about the quotes and double quotes.
Writing javascript code, intended to be run on the client, on the server is to put it simply: bad, wrong, to be avoided.
You should prefer to write your javascript functions in separate js files and only invoke them from the server. The benefit of this is that you will no longer have to worry about single, double and triple quotes, your js will be cached, minified, gzipped, served from a CDN, optimized, ... The end result of mixing server side languages such as C#/VB.NET with javascript is just ugly and difficult to maintain code.
Now to the point. When you need to call some javascript function from the server and you need to pass it some arguments in order to not worry about quotes and stuff, I would recommend you to JSON serialize your server side object and pass it to the client function.
Let's take an example. Suppose that you have written a function which requires some arguments:
function foo(myModel) {
alert(myModel.Prop1 + ' | ' + myModel.Prop2);
}
and now you want to invoke this function from the server, here's how to proceed:
var model = new
{
Prop1 = #"some value that can contain ', \, "", anything you like to throw it in, etc..",
Prop2 = "some other value"
};
var json = new JavaScriptSerializer().Serialize(model);
var script = string.Format("foo({0});", json);
ClientScript.RegisterStartupScript(GetType(), "foo", script, true);
Now you no longer need to worry about any quotes and escaping. No matter what value you throw in those properties, they will be correctly serialized when invoking the javascript function.
Related
NOTE: This is not for web programming. We use javascript to interface with low level hardware, hence let's not go with jQuery APIs etc.
I have a javascript file that performs a sequence of actions on a device, and I have a python file that will be invoked later to validate these actions. There is a set of hardware information hard-coded in both javascript file and python file. I want to avoid this duplication of information by putting these info into a JSON file so both can access it.
// Javascript
var hardware_info = JSON.parse(load('hardware.json'));
// load() is probably not standard javascript API, but it basically copies that code into the existing script.
Already failed by this step because 'hardware.json' is not using javascript syntax...
I already validated the json using jshint/jslint, hardware.json looks like this:
{
"hardware1": {
"ID": "xxx"
},
"hardware2": {
"ID": "yyy"
}
}
The following Python works well for accessing the json, there is not much to it:
with open('hardware.json', 'r') as f:
data = json.load(f)
It looks like load() executes the specified file, not read it and return the contents. If this is your only option to read another file, then I suggest you use JSONP instead of JSON.
JSONP works by adding a callback around the data. Instead of:
{"key": "value"}
the file contains a function call with the data being passed in:
callback({"key": "value"});
This is meant to be executed by a JavaScript engine, causing it to execute the callback. load() would execute your file, and the callback function would be called as a result, passing in the data.
When used on the web, you'd call a JSONP service and pass in the name of the callback the service should add, but when just sharing a configuration file between a JS engine and Python, you'd hardcode that callback name.
In Python, you'd have to strip off the callback text before loading it as JSON data. That could be as easy as just removing the first N and last M characters:
with open('hardware.json', 'r') as f:
jsonp_data = f.read()
# remove first 9 and last 3 characters to remove JSONP callback
data = json.loads(jsonp_data[9:-3])
A little more sophisticated technique could use newlines:
callback(
{"key": "value"}
);
to make it easier to remove the first and last line in Python. Or you could use jsonp_data.partition('(')[-1].jsonp.rpartition(')')[0] to take everything between the first ( and the last ) character in the string. Etc.
I am trying to write razor code inside javascript where I am trying to use a local variable inside the razor code. Here is the sample code:
<script type="text/javascript">
for (i = 0; i < data.result.length; i++) {
$("#member-table tbody").append("<tr>");
var id = data.result[i].MemberId;
var actions = $("<td>" + #Html.ActionLink("Detay", "Edit", new { id }) + "</td>)");
}
</script>
the problem is that id is not recognized by the razor code (i.e. it does not exist in the current context). How can I achieve that ? Is there any way ?
It's not possible to access a javascript variable in a razor block.
That's because razor is executed in the server, and javascript is executed in the browser.
However, by looking at your code it seems like you are using javascript to populate a table and that's bad, there are two patterns for solving this problem, one that solves everything in the server, and another one that solves everything in the browser.
Solving everything in the server:
If you decide that you want to solve everything in the server, your javascript should request the contents from the server and load them into a placeholder without changing them, something like:
$("#myButton").click(function(){
$("#myDinamicDiv").load("/Path/ToView");
});
and then you use razor's foreach loop to generate the table's html:
#foreach (var x in ViewBag.MyData)
{
<tr>
<td>Generate contents here, including links </td>
</tr>
}
Solving everything in the client:
As pointed out in another answer, if you are using the default routing, you can just create direct strings in the javascript code and add them to your page, keep in mind however, that when using this solution, as your page gets complex, your javascript will became less and less maintainable, having a for loop that iterates over data is a sign that maybe you can benefit from javascript UI frameworks like Angular.js and Knockout.js, in fact, what you are doing is the core of Knockout.js's third lesson in its tutorial (Single page applications)
If you're just using default routing, then simply just don't bother with the Razor #Html.ActionLink. Stick with an explicit tag:
var actions = $('<td>Detay</td>');
...obviously with whatever your current controller name is substituted for [your-controller-here].
(And I'm assuming your 'id' isn't necessarily URL-encoded, hence the 'escape'.)
You are mixing server side and client side here. You cannot create #Html.ActioLink using client side variables. Html.ActionLink is rendered on the server, it does not have any clue at all about your client side variables.
If you want to use a client side variable, like "id", render a plain html link (a) tag.
This worked for me once
if ('#ViewBag.DownloadLink' != '') {
window.location.href = '#ViewBag.DownloadLink';
}
I have a data javascript file, which is being dynamically added to website via some custom code.
This file comes from a third party vendor, who could potentially add malicious code in the file
Before this file is added to the website, I would like to parse through it, and look for malicious code, such as redirects or alerts, that inherently get executed upon a files inclusion in the project/website.
For example, my js file could look like this :
alert ('i am malicious');
var IAmGoodData =
[
{ Name :'test', Type:'Test2 },
{ Name :'test1', Type:'Test21' },
{ Name :'test2', Type:'Test22' }
]
I load this file into a object via a XMLHttpRequest call, and when this call returns, I can use the variable (which is my file text) and search it for words:
var client = new XMLHttpRequest();
client.open('GET', 'folder/fileName.js');
client.onreadystatechange = function()
{
ScanText(client.responseText);
}
client.send();
function ScanText(text)
{
alert(text);
var index = text.search('alert'); //Here i can search for keywords
}
The last line would return index of 0, as the word alert is found at index 0 in the file.
Questions:
Is there a more efficient way to search for keywords in the file?
What specific keywords should i be searching for to prevent malicious code being run? ie redirects, popups, sounds etc.....
Instead of having them include var IAmGoodData =, make them simply provide JSON (which is basically what the rest of the file is, or seems to be). Then you parse it as JSON, using JSON.parse(). If it fails, they either didn't follow the JSON format well, or have external code, and in either case you would ignore the response.
For example, you'd expect data from the external file like:
[
{ Name :'test', Type:'Test2' },
{ Name :'test1', Type:'Test21' },
{ Name :'test2', Type:'Test22' }
]
which needs to be properly serialized as JSON (double quotes instead of single quotes, and double quotes around the keys). In your code, you'd use:
var json;
try {
json = JSON.parse(client.responseText);
catch (ex) {
// Invalid JSON
}
if (json) {
// Do something with the response
}
Then you could loop over json and access the Name and Type properties of each.
Random Note:
In your client.onreadystatechange callback, make sure you check client.readyState === 4 && client.status === 200, to know that the request was successful and is done.
This is extremely difficult to do. There are no intrinsically malicious keywords or functions in JavaScript, there are malicious applications. You could be getting false positives for "malicious" activity and prevent a legitimate code with a real purpose from being executed. And at the same time, anyone with a little bit of imagination could bypass any "preventive" method you may implement.
I'd suggest you look for a different approach. This is one of those problems (like CAPTCHA) in which it's trivial for a human to solve while for a machine is practically impossible to do so. You could try having a moderator or some human evaluator to interpret the code and accept it.
You should have them provide valid JSON rather than arbitrary Javascript.
You can then call JSON.parse() to read their data without any risk of code execution.
In short, data is not code, and should not be able to contain code.
You shouldn't. The user should be allowed to type whatever they want, and it's your job to display it.
It all depends on where it is being put, of course:
Database: mysql_real_escape_string or equivalent for whatever engine you're using.
HTML: htmlspecialchars in PHP, createTextNode or .replace(/</g,"<") in JavaScript
JavaScript: json_encode in PHP, JSON.stringify in JavaScript.
At the end of the day, just don't be Yahoo
I have a gsp page (template) where I need to include some javascript. In the example below, how would I get the remoteFunction to understand, the moneyTransId will be set by the javascript function? MoneyTransId comes out fine in the alert, but I can't get it to work in the remoteFunction, and apparently need to escape it somehow.
<script type="text/javascript">
function confirmVoid(moneyTransId) {
var r = confirm("Please confirm the void");
if (r == true) {
alert("ID is: " +moneyTransId);
${remoteFunction(action:"voidTransaction", id:moneyTransId)};
...
Use the following syntax:
${remoteFunction(action:'voidTransaction', params:'\'id=\'+moneyTransId')};
This way, you won't mix server-side code with client-side code.
Hope this helps.
Server side variables and statements can not read client side (javascript) variables.
Server side code runs first, then html and javascript get generated and sent to the client (browser). Then the browser renders HTML and runs javascript. Hope this helps your thought process.
Dmitry.
boolean canModify = UTIL.hasSecurity("PFTMODFY") && something;
function name() {
I need to pass a value false to something when the page loads.
}
window.onLoad = name
How can i pass a value from JavaScript to JSP on the page load
I think you mean it the other way around, have server-side code output a value that JavaScript can see at page-load time.
Sending from your server code (JSP) to your client code (JavaScript)
Just output it like you would anything else, e.g.:
<%
boolean canModify = UTIL.hasSecurity("PFTMODFY") && something;
%>
var canModify = <%=canModify%>;
// ^ ^
// | +-- server-side variable
// +-- client-side variable
When the JSP actually runs, the script code returned to the client will simply be
var canModify = false;
or
var canModify = true;
That's a boolean; if you need to output a string, you need to put the quotes around it and be careful that you escape anything within it that should be escaped inside a JavaScript literal string (like a backslash, for instance, and whatever quote character you're using).
Sending from your client code (JavaScript) to your server code (JSP)
But if you really mean you want to send a value back to the server on page load (which seems odd, but hey), you'd have to use Ajax for that. If you're going to be doing Ajax stuff, I'd recommend using a library like jQuery, Closure, Prototype, YUI, or any of several others as they can dramatically simplify the process for you. For instance, using jQuery, this client-side code sends a value back to the server:
jQuery.get("/your/page/url", {"name": "value"});
(or jQuery.post for things that make changes). Using Prototype, it'd be:
new Ajax.Request("/your/page/url", {
method: "GET", // or, of couse, "POST"
parameters: {"name": "value"}
});
All of the libs I mentioned above have similarly easy-to-use mechanisms for sending data to the server. Note that this mechanism is bound by the Same Origin Policy.
You don't need a library for this, of course — anything a library can do, you can do yourself. The features I've listed above are all wrappers for the XMLHttpRequest object (Wikipedia, MSDN, MDC). See the linked resources for examples.
Non-Ajax hack
I shouldn't have said you need to use Ajax for this, more like you want to. :-) If, for some reason, you really didn't want to use Ajax you could do it by adding something to the page with JavaScript that triggers a retrieval from the server, and then include your value as a flag in that request. For instance:
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.src = "/path/to/jsp?name=" + encodeURIComponent(value);
document.getElementsByTagName('head')[0].appendChild(link);
Your JSP would do whatever it needs to do with the query string, and then return anything that's valid in a stylesheet (/* */, for instance). Or if you don't want to use a style sheet link, use an img tag and return a transparent pixel; etc.
But I wouldn't do that. I'd use Ajax.